| /*------------------------------------------------------------------------- |
| * 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 "gl4cES31CompatibilityTests.hpp" |
| #include "gluContextInfo.hpp" |
| #include "glwEnums.hpp" |
| #include "tcuMatrix.hpp" |
| #include "tcuRenderTarget.hpp" |
| #include "tcuVectorUtil.hpp" |
| #include <assert.h> |
| #include <cstdarg> |
| #include <map> |
| |
| namespace gl4cts |
| { |
| namespace es31compatibility |
| { |
| using namespace glw; |
| namespace |
| { |
| typedef tcu::Vec2 vec2; |
| typedef tcu::Vec4 vec4; |
| typedef tcu::IVec4 ivec4; |
| typedef tcu::UVec4 uvec4; |
| typedef tcu::Mat4 mat4; |
| |
| enum Target |
| { |
| T2D = 0, |
| T3D, |
| TCM, |
| T2DA |
| }; |
| |
| const char* const kGLSLVer = "#version 310 es"; |
| const char* const kGLSLSIA = NL "#extension GL_OES_shader_image_atomic : require"; |
| const char* const kGLSLPrec = |
| NL "precision highp float;" NL "precision highp int;" NL "precision highp sampler2D;" NL |
| "precision highp sampler3D;" NL "precision highp samplerCube;" NL "precision highp sampler2DArray;" NL |
| "precision highp isampler2D;" NL "precision highp isampler3D;" NL "precision highp isamplerCube;" NL |
| "precision highp isampler2DArray;" NL "precision highp usampler2D;" NL "precision highp usampler3D;" NL |
| "precision highp usamplerCube;" NL "precision highp usampler2DArray;" NL "precision highp image2D;" NL |
| "precision highp image3D;" NL "precision highp imageCube;" NL "precision highp image2DArray;" NL |
| "precision highp iimage2D;" NL "precision highp iimage3D;" NL "precision highp iimageCube;" NL |
| "precision highp iimage2DArray;" NL "precision highp uimage2D;" NL "precision highp uimage3D;" NL |
| "precision highp uimageCube;" NL "precision highp uimage2DArray;"; |
| |
| class ShaderImageLoadStoreBase : public deqp::SubcaseBase |
| { |
| public: |
| virtual std::string Title() |
| { |
| return ""; |
| } |
| |
| virtual std::string Purpose() |
| { |
| return ""; |
| } |
| |
| virtual std::string Method() |
| { |
| return ""; |
| } |
| |
| virtual std::string PassCriteria() |
| { |
| return ""; |
| } |
| |
| bool IsVSFSAvailable(int requiredVS, int requiredFS) |
| { |
| GLint imagesVS, imagesFS; |
| glGetIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS, &imagesVS); |
| glGetIntegerv(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, &imagesFS); |
| if (imagesVS >= requiredVS && imagesFS >= requiredFS) |
| return true; |
| else |
| { |
| std::ostringstream reason; |
| reason << "Required " << requiredVS << " VS image uniforms but only " << imagesVS << " available." |
| << std::endl |
| << "Required " << requiredFS << " FS image uniforms but only " << imagesFS << " available." |
| << std::endl; |
| OutputNotSupported(reason.str()); |
| return false; |
| } |
| } |
| bool IsSSBInVSFSAvailable(int required) |
| { |
| GLint blocksVS, blocksFS; |
| glGetIntegerv(GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS, &blocksVS); |
| glGetIntegerv(GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS, &blocksFS); |
| if (blocksVS >= required && blocksFS >= required) |
| return true; |
| else |
| { |
| std::ostringstream reason; |
| reason << "Required " << required << " VS storage blocks but only " << blocksVS << " available." |
| << std::endl |
| << "Required " << required << " FS storage blocks but only " << blocksFS << " available." |
| << std::endl; |
| OutputNotSupported(reason.str()); |
| return false; |
| } |
| } |
| |
| bool IsImageAtomicSupported() |
| { |
| bool is_at_least_gl_45 = |
| (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5))); |
| bool is_arb_es31_compatibility = m_context.getContextInfo().isExtensionSupported("GL_ARB_ES3_1_compatibility"); |
| if (!(is_at_least_gl_45 || is_arb_es31_compatibility)) |
| { |
| std::ostringstream reason; |
| reason << "Required GL_OES_shader_image_atomic is not available." << std::endl; |
| OutputNotSupported(reason.str()); |
| return false; |
| } |
| return true; |
| } |
| |
| bool AreOutputsAvailable(int required) |
| { |
| GLint outputs; |
| glGetIntegerv(GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES, &outputs); |
| if (outputs < required) |
| { |
| std::ostringstream reason; |
| reason << "Required " << required << " shader output resources but only " << outputs << " available." |
| << std::endl; |
| OutputNotSupported(reason.str()); |
| return false; |
| } |
| return true; |
| } |
| |
| 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; |
| } |
| |
| bool Equal(const vec4& v0, const vec4& v1, GLenum internalformat) |
| { |
| if (internalformat == GL_RGBA8_SNORM || internalformat == GL_RGBA8) |
| { |
| return ColorEqual(v0, v1, vec4(0.01f)); |
| } |
| return (v0[0] == v1[0]) && (v0[1] == v1[1]) && (v0[2] == v1[2]) && (v0[3] == v1[3]); |
| } |
| bool Equal(const ivec4& a, const ivec4& b, GLenum) |
| { |
| return (a[0] == b[0]) && (a[1] == b[1]) && (a[2] == b[2]) && (a[3] == b[3]); |
| } |
| bool Equal(const uvec4& a, const uvec4& b, GLenum) |
| { |
| return (a[0] == b[0]) && (a[1] == b[1]) && (a[2] == b[2]) && (a[3] == b[3]); |
| } |
| |
| 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(); |
| } |
| |
| template <typename T> |
| bool CompareValues(T* map_data, int kSize, const T& expected_value, GLenum internalformat = 0, int layers = 1) |
| { |
| for (int i = 0; i < kSize * kSize * layers; ++i) |
| { |
| if (!Equal(map_data[i], expected_value, internalformat)) |
| { |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << "[" << i << "] Value is: " << ToString(map_data[i]).c_str() |
| << ". Value should be: " << ToString(expected_value).c_str() << "." << tcu::TestLog::EndMessage; |
| return false; |
| } |
| } |
| return true; |
| } |
| template <typename T> |
| bool CompareValues(bool always, T* map_data, int kSize, const T& expected_value, GLenum internalformat = 0, |
| int layers = 1) |
| { |
| (void)internalformat; |
| for (int i = 0; i < kSize * kSize * layers; ++i) |
| { |
| if (always) |
| { |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << "[" << i << "] Value is: " << ToString(map_data[i]).c_str() |
| << ". Value should be: " << ToString(expected_value).c_str() << "." << tcu::TestLog::EndMessage; |
| } |
| } |
| return true; |
| } |
| |
| bool CheckFB(vec4 expected) |
| { |
| const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget(); |
| const tcu::PixelFormat& pixelFormat = renderTarget.getPixelFormat(); |
| vec4 g_color_eps = vec4(1.f / (float)(1 << pixelFormat.redBits), 1.f / (float)(1 << pixelFormat.greenBits), |
| 1.f / (float)(1 << pixelFormat.blueBits), 1.f); |
| vec4 g_color_max = vec4(255); |
| std::vector<GLubyte> fb(getWindowWidth() * getWindowHeight() * 4); |
| int fb_w = getWindowWidth(); |
| int fb_h = getWindowHeight(); |
| glReadPixels(0, 0, fb_w, fb_h, GL_RGBA, GL_UNSIGNED_BYTE, &fb[0]); |
| for (GLint i = 0, y = 0; y < fb_h; ++y) |
| for (GLint x = 0; x < fb_w; ++x, i += 4) |
| { |
| if (fabs(fb[i + 0] / g_color_max[0] - expected[0]) > g_color_eps[0] || |
| fabs(fb[i + 1] / g_color_max[1] - expected[1]) > g_color_eps[1] || |
| fabs(fb[i + 2] / g_color_max[2] - expected[2]) > g_color_eps[2]) |
| { |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << "Incorrect framebuffer color at pixel (" << x << ", " << y |
| << "). Color is (" << fb[i + 0] / g_color_max[0] << ", " << fb[i + 1] / g_color_max[1] << ", " |
| << fb[i + 2] / g_color_max[2] << "). Color should be (" << expected[0] << ", " << expected[1] |
| << ", " << expected[2] << ")." << tcu::TestLog::EndMessage; |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| bool CompileShader(GLuint shader) |
| { |
| glCompileShader(shader); |
| |
| GLint status; |
| glGetShaderiv(shader, GL_COMPILE_STATUS, &status); |
| if (status == GL_FALSE) |
| { |
| GLsizei length; |
| GLchar log[1024]; |
| glGetShaderInfoLog(shader, sizeof(log), &length, log); |
| if (length > 1) |
| { |
| m_context.getTestContext().getLog() << tcu::TestLog::Message << "Shader Info Log:\n" |
| << log << tcu::TestLog::EndMessage; |
| } |
| return false; |
| } |
| return true; |
| } |
| |
| bool LinkProgram(GLuint program) |
| { |
| glLinkProgram(program); |
| |
| GLint status; |
| glGetProgramiv(program, GL_LINK_STATUS, &status); |
| if (status == GL_FALSE) |
| { |
| GLsizei length; |
| GLchar log[1024]; |
| glGetProgramInfoLog(program, sizeof(log), &length, log); |
| if (length > 1) |
| { |
| m_context.getTestContext().getLog() << tcu::TestLog::Message << "Shader Info Log:\n" |
| << log << tcu::TestLog::EndMessage; |
| } |
| return false; |
| } |
| return true; |
| } |
| |
| GLuint BuildProgram(const char* src_vs, const char* src_fs, bool SIAvs = false, bool SIAfs = false) |
| { |
| std::ostringstream osvs, osfs; |
| osvs << kGLSLVer << (SIAvs ? kGLSLSIA : "\n") << kGLSLPrec; |
| osfs << kGLSLVer << (SIAfs ? kGLSLSIA : "\n") << kGLSLPrec; |
| std::string hvs = osvs.str(); |
| std::string hfs = osfs.str(); |
| |
| const GLuint p = glCreateProgram(); |
| |
| if (src_vs) |
| { |
| GLuint sh = glCreateShader(GL_VERTEX_SHADER); |
| glAttachShader(p, sh); |
| glDeleteShader(sh); |
| const char* const src[2] = { hvs.c_str(), src_vs }; |
| glShaderSource(sh, 2, src, NULL); |
| if (!CompileShader(sh)) |
| { |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << src[0] << src[1] << tcu::TestLog::EndMessage; |
| return p; |
| } |
| } |
| if (src_fs) |
| { |
| GLuint sh = glCreateShader(GL_FRAGMENT_SHADER); |
| glAttachShader(p, sh); |
| glDeleteShader(sh); |
| const char* const src[2] = { hfs.c_str(), src_fs }; |
| glShaderSource(sh, 2, src, NULL); |
| if (!CompileShader(sh)) |
| { |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << src[0] << src[1] << tcu::TestLog::EndMessage; |
| return p; |
| } |
| } |
| if (!LinkProgram(p)) |
| { |
| if (src_vs) |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << hvs.c_str() << src_vs << tcu::TestLog::EndMessage; |
| if (src_fs) |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << hfs.c_str() << src_fs << tcu::TestLog::EndMessage; |
| return p; |
| } |
| |
| return p; |
| } |
| |
| GLuint CreateComputeProgram(const std::string& cs, bool SIA = false) |
| { |
| std::ostringstream oscs; |
| oscs << kGLSLVer << (SIA ? kGLSLSIA : "\n") << kGLSLPrec; |
| std::string hcs = oscs.str(); |
| const GLuint p = glCreateProgram(); |
| |
| if (!cs.empty()) |
| { |
| const GLuint sh = glCreateShader(GL_COMPUTE_SHADER); |
| glAttachShader(p, sh); |
| glDeleteShader(sh); |
| const char* const src[2] = { hcs.c_str(), cs.c_str() }; |
| glShaderSource(sh, 2, src, NULL); |
| if (!CompileShader(sh)) |
| { |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << src[0] << src[1] << tcu::TestLog::EndMessage; |
| return p; |
| } |
| } |
| if (!LinkProgram(p)) |
| { |
| if (!cs.empty()) |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << hcs.c_str() << cs.c_str() << tcu::TestLog::EndMessage; |
| return p; |
| } |
| |
| return p; |
| } |
| |
| GLuint BuildShaderProgram(GLenum type, const char* src) |
| { |
| const char* const src3[3] = { kGLSLVer, kGLSLPrec, src }; |
| const GLuint p = glCreateShaderProgramv(type, 3, src3); |
| GLint status; |
| glGetProgramiv(p, GL_LINK_STATUS, &status); |
| if (status == GL_FALSE) |
| { |
| GLchar log[1024]; |
| glGetProgramInfoLog(p, sizeof(log), NULL, log); |
| m_context.getTestContext().getLog() << tcu::TestLog::Message << "Program Info Log:\n" |
| << log << "\n" |
| << src3[0] << "\n" |
| << src3[1] << "\n" |
| << src3[2] << tcu::TestLog::EndMessage; |
| } |
| return p; |
| } |
| |
| void CreateFullViewportQuad(GLuint* vao, GLuint* vbo, GLuint* ebo) |
| { |
| assert(vao && vbo); |
| |
| // interleaved data (vertex, color0 (green), color1 (blue), color2 (red)) |
| const float v[] = { |
| -1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, -1.0f, 0.0f, 1.0f, |
| 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, |
| 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, |
| }; |
| glGenBuffers(1, vbo); |
| glBindBuffer(GL_ARRAY_BUFFER, *vbo); |
| glBufferData(GL_ARRAY_BUFFER, sizeof(v), v, GL_STATIC_DRAW); |
| glBindBuffer(GL_ARRAY_BUFFER, 0); |
| |
| if (ebo) |
| { |
| std::vector<GLushort> index_data(4); |
| for (int i = 0; i < 4; ++i) |
| { |
| index_data[i] = static_cast<GLushort>(i); |
| } |
| glGenBuffers(1, ebo); |
| glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, *ebo); |
| glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLushort) * 4, &index_data[0], GL_STATIC_DRAW); |
| glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); |
| } |
| |
| glGenVertexArrays(1, vao); |
| glBindVertexArray(*vao); |
| glBindBuffer(GL_ARRAY_BUFFER, *vbo); |
| glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 11, 0); |
| |
| glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 11, reinterpret_cast<void*>(sizeof(float) * 2)); |
| |
| glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 11, |
| |
| reinterpret_cast<void*>(sizeof(float) * 5)); |
| |
| glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 11, reinterpret_cast<void*>(sizeof(float) * 8)); |
| |
| glBindBuffer(GL_ARRAY_BUFFER, 0); |
| glEnableVertexAttribArray(0); |
| glEnableVertexAttribArray(1); |
| glEnableVertexAttribArray(2); |
| glEnableVertexAttribArray(3); |
| if (ebo) |
| { |
| glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, *ebo); |
| } |
| glBindVertexArray(0); |
| } |
| |
| std::string FormatEnumToString(GLenum e) |
| { |
| switch (e) |
| { |
| case GL_RGBA32F: |
| return "rgba32f"; |
| case GL_RGBA16F: |
| return "rgba16f"; |
| case GL_R32F: |
| return "r32f"; |
| |
| case GL_RGBA32UI: |
| return "rgba32ui"; |
| case GL_RGBA16UI: |
| return "rgba16ui"; |
| case GL_RGBA8UI: |
| return "rgba8ui"; |
| case GL_R32UI: |
| return "r32ui"; |
| |
| case GL_RGBA32I: |
| return "rgba32i"; |
| case GL_RGBA16I: |
| return "rgba16i"; |
| case GL_RGBA8I: |
| return "rgba8i"; |
| case GL_R32I: |
| return "r32i"; |
| |
| case GL_RGBA8: |
| return "rgba8"; |
| |
| case GL_RGBA8_SNORM: |
| return "rgba8_snorm"; |
| } |
| |
| assert(0); |
| return ""; |
| } |
| |
| template <typename T> |
| GLenum Format(); |
| |
| template <typename T> |
| GLenum Type(); |
| |
| template <typename T> |
| std::string TypePrefix(); |
| |
| template <typename T> |
| GLenum ImageType(GLenum target); |
| |
| void ClearBuffer(GLenum buffer, GLint drawbuffer, const vec4& color) |
| { |
| glClearBufferfv(buffer, drawbuffer, &color[0]); |
| } |
| |
| void ClearBuffer(GLenum buffer, GLint drawbuffer, const ivec4& color) |
| { |
| glClearBufferiv(buffer, drawbuffer, &color[0]); |
| } |
| |
| void ClearBuffer(GLenum buffer, GLint drawbuffer, const uvec4& color) |
| { |
| glClearBufferuiv(buffer, drawbuffer, &color[0]); |
| } |
| |
| bool CheckMax(GLenum pname, GLint min_value) |
| { |
| GLboolean b; |
| GLint i; |
| GLfloat f; |
| GLint64 i64; |
| |
| glGetIntegerv(pname, &i); |
| if (i < min_value) |
| return false; |
| |
| glGetBooleanv(pname, &b); |
| if (b != (i ? GL_TRUE : GL_FALSE)) |
| return false; |
| |
| glGetFloatv(pname, &f); |
| if (static_cast<GLint>(f) < min_value) |
| return false; |
| |
| glGetInteger64v(pname, &i64); |
| if (static_cast<GLint>(i64) < min_value) |
| return false; |
| |
| return true; |
| } |
| |
| bool CheckBinding(GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, |
| GLenum format) |
| { |
| GLint i; |
| GLboolean b; |
| |
| glGetIntegeri_v(GL_IMAGE_BINDING_NAME, unit, &i); |
| if (static_cast<GLuint>(i) != texture) |
| { |
| m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_NAME is " << i |
| << " should be " << texture << "." << tcu::TestLog::EndMessage; |
| return false; |
| } |
| |
| glGetIntegeri_v(GL_IMAGE_BINDING_LEVEL, unit, &i); |
| if (i != level) |
| { |
| m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_LEVEL is " << i |
| << " should be " << level << "." << tcu::TestLog::EndMessage; |
| return false; |
| } |
| |
| glGetIntegeri_v(GL_IMAGE_BINDING_LAYERED, unit, &i); |
| glGetBooleani_v(GL_IMAGE_BINDING_LAYERED, unit, &b); |
| if (i != layered || b != layered) |
| { |
| m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_LAYERED is " << i |
| << " should be " << layered << "." << tcu::TestLog::EndMessage; |
| return false; |
| } |
| |
| glGetIntegeri_v(GL_IMAGE_BINDING_LAYER, unit, &i); |
| if (i != layer) |
| { |
| m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_LAYER is " << i |
| << " should be " << layer << "." << tcu::TestLog::EndMessage; |
| return false; |
| } |
| |
| glGetIntegeri_v(GL_IMAGE_BINDING_ACCESS, unit, &i); |
| if (static_cast<GLenum>(i) != access) |
| { |
| m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_ACCESS is " << i |
| << " should be " << access << "." << tcu::TestLog::EndMessage; |
| return false; |
| } |
| |
| glGetIntegeri_v(GL_IMAGE_BINDING_FORMAT, unit, &i); |
| if (static_cast<GLenum>(i) != format) |
| { |
| m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_FORMAT is " << i |
| << " should be " << format << "." << tcu::TestLog::EndMessage; |
| return false; |
| } |
| |
| return true; |
| } |
| const char* EnumToString(GLenum e) |
| { |
| switch (e) |
| { |
| case GL_TEXTURE_2D: |
| return "GL_TEXTURE_2D"; |
| case GL_TEXTURE_3D: |
| return "GL_TEXTURE_3D"; |
| case GL_TEXTURE_CUBE_MAP: |
| return "GL_TEXTURE_CUBE_MAP"; |
| case GL_TEXTURE_2D_ARRAY: |
| return "GL_TEXTURE_2D_ARRAY"; |
| |
| default: |
| assert(0); |
| break; |
| } |
| return NULL; |
| } |
| }; |
| |
| template <> |
| GLenum ShaderImageLoadStoreBase::Format<vec4>() |
| { |
| return GL_RGBA; |
| } |
| |
| template <> |
| GLenum ShaderImageLoadStoreBase::Format<ivec4>() |
| { |
| return GL_RGBA_INTEGER; |
| } |
| |
| template <> |
| GLenum ShaderImageLoadStoreBase::Format<uvec4>() |
| { |
| return GL_RGBA_INTEGER; |
| } |
| |
| template <> |
| GLenum ShaderImageLoadStoreBase::Format<GLint>() |
| { |
| return GL_RED_INTEGER; |
| } |
| |
| template <> |
| GLenum ShaderImageLoadStoreBase::Format<GLuint>() |
| { |
| return GL_RED_INTEGER; |
| } |
| |
| template <> |
| GLenum ShaderImageLoadStoreBase::Type<vec4>() |
| { |
| return GL_FLOAT; |
| } |
| |
| template <> |
| GLenum ShaderImageLoadStoreBase::Type<ivec4>() |
| { |
| return GL_INT; |
| } |
| |
| template <> |
| GLenum ShaderImageLoadStoreBase::Type<uvec4>() |
| { |
| return GL_UNSIGNED_INT; |
| } |
| |
| template <> |
| GLenum ShaderImageLoadStoreBase::Type<GLint>() |
| { |
| return GL_INT; |
| } |
| |
| template <> |
| GLenum ShaderImageLoadStoreBase::Type<GLuint>() |
| { |
| return GL_UNSIGNED_INT; |
| } |
| |
| template <> |
| std::string ShaderImageLoadStoreBase::TypePrefix<vec4>() |
| { |
| return ""; |
| } |
| |
| template <> |
| |
| std::string ShaderImageLoadStoreBase::TypePrefix<ivec4>() |
| { |
| return "i"; |
| } |
| |
| template <> |
| std::string ShaderImageLoadStoreBase::TypePrefix<uvec4>() |
| { |
| return "u"; |
| } |
| |
| template <> |
| |
| std::string ShaderImageLoadStoreBase::TypePrefix<GLint>() |
| { |
| return "i"; |
| } |
| |
| template <> |
| std::string ShaderImageLoadStoreBase::TypePrefix<GLuint>() |
| { |
| return "u"; |
| } |
| |
| template <> |
| GLenum ShaderImageLoadStoreBase::ImageType<vec4>(GLenum target) |
| { |
| switch (target) |
| { |
| case GL_TEXTURE_2D: |
| return GL_IMAGE_2D; |
| case GL_TEXTURE_3D: |
| return GL_IMAGE_3D; |
| case GL_TEXTURE_CUBE_MAP: |
| return GL_IMAGE_CUBE; |
| case GL_TEXTURE_2D_ARRAY: |
| return GL_IMAGE_2D_ARRAY; |
| } |
| assert(0); |
| return 0; |
| } |
| |
| template <> |
| GLenum ShaderImageLoadStoreBase::ImageType<ivec4>(GLenum target) |
| { |
| switch (target) |
| { |
| case GL_TEXTURE_2D: |
| return GL_INT_IMAGE_2D; |
| case GL_TEXTURE_3D: |
| return GL_INT_IMAGE_3D; |
| case GL_TEXTURE_CUBE_MAP: |
| return GL_INT_IMAGE_CUBE; |
| case GL_TEXTURE_2D_ARRAY: |
| return GL_INT_IMAGE_2D_ARRAY; |
| } |
| assert(0); |
| return 0; |
| } |
| |
| template <> |
| GLenum ShaderImageLoadStoreBase::ImageType<uvec4>(GLenum target) |
| { |
| switch (target) |
| { |
| case GL_TEXTURE_2D: |
| return GL_UNSIGNED_INT_IMAGE_2D; |
| case GL_TEXTURE_3D: |
| return GL_UNSIGNED_INT_IMAGE_3D; |
| case GL_TEXTURE_CUBE_MAP: |
| return GL_UNSIGNED_INT_IMAGE_CUBE; |
| case GL_TEXTURE_2D_ARRAY: |
| return GL_UNSIGNED_INT_IMAGE_2D_ARRAY; |
| } |
| assert(0); |
| return 0; |
| } |
| |
| int Components(GLenum e) |
| { |
| return (e == GL_RED || e == GL_RED_INTEGER) ? 1 : 4; |
| } |
| |
| bool Shorts(GLenum e) |
| { |
| return (e == GL_RGBA16I || e == GL_RGBA16UI); |
| } |
| |
| bool Bytes(GLenum e) |
| { |
| return (e == GL_RGBA8I || e == GL_RGBA8UI || e == GL_RGBA8 || e == GL_RGBA8_SNORM); |
| } |
| |
| template <typename T> |
| class ShortByteData |
| { |
| public: |
| std::vector<T> data; |
| std::vector<GLshort> datas; |
| std::vector<GLbyte> datab; |
| |
| ShortByteData(int size, const T& value, GLenum internalformat, GLenum format) |
| : data(size * size, value), datas(size * size * 4), datab(size * size * 4) |
| { |
| if (Components(format) == 1) |
| for (unsigned i = 0; i < data.size() / 4; ++i) |
| { |
| data[i][0] = data[i * 4][0]; |
| data[i][1] = data[i * 4 + 1][0]; |
| data[i][2] = data[i * 4 + 2][0]; |
| data[i][3] = data[i * 4 + 3][0]; |
| } |
| if (Shorts(internalformat)) |
| { |
| for (unsigned i = 0; i < datas.size(); i += 4) |
| { |
| datas[i] = static_cast<GLshort>(data[i / 4][0]); |
| datas[i + 1] = static_cast<GLshort>(data[i / 4][1]); |
| datas[i + 2] = static_cast<GLshort>(data[i / 4][2]); |
| datas[i + 3] = static_cast<GLshort>(data[i / 4][3]); |
| } |
| } |
| if (Bytes(internalformat)) |
| { |
| for (unsigned i = 0; i < datas.size(); i += 4) |
| { |
| if (internalformat == GL_RGBA8I || internalformat == GL_RGBA8UI) |
| { |
| datab[i] = static_cast<GLbyte>(data[i / 4][0]); |
| datab[i + 1] = static_cast<GLbyte>(data[i / 4][1]); |
| datab[i + 2] = static_cast<GLbyte>(data[i / 4][2]); |
| datab[i + 3] = static_cast<GLbyte>(data[i / 4][3]); |
| } |
| else if (internalformat == GL_RGBA8) |
| { |
| datab[i] = static_cast<GLbyte>(data[i / 4][0] * 255); |
| datab[i + 1] = static_cast<GLbyte>(data[i / 4][1] * 255); |
| datab[i + 2] = static_cast<GLbyte>(data[i / 4][2] * 255); |
| datab[i + 3] = static_cast<GLbyte>(data[i / 4][3] * 255); |
| } |
| else |
| { // GL_RGBA8_SNORM |
| datab[i] = static_cast<GLbyte>(data[i / 4][0] * 127); |
| datab[i + 1] = static_cast<GLbyte>(data[i / 4][1] * 127); |
| datab[i + 2] = static_cast<GLbyte>(data[i / 4][2] * 127); |
| datab[i + 3] = static_cast<GLbyte>(data[i / 4][3] * 127); |
| } |
| } |
| } |
| } |
| }; |
| |
| //----------------------------------------------------------------------------- |
| // 1.1.1 BasicAPIGet |
| //----------------------------------------------------------------------------- |
| class BasicAPIGet : public ShaderImageLoadStoreBase |
| { |
| virtual long Run() |
| { |
| if (!CheckMax(GL_MAX_IMAGE_UNITS, 4)) |
| { |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << "GL_MAX_IMAGE_UNITS value is invalid." << tcu::TestLog::EndMessage; |
| return ERROR; |
| } |
| if (!CheckMax(GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES, 4)) |
| { |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << "GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES value is invalid." |
| << tcu::TestLog::EndMessage; |
| return ERROR; |
| } |
| if (!CheckMax(GL_MAX_VERTEX_IMAGE_UNIFORMS, 0)) |
| { |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << "GL_MAX_VERTEX_IMAGE_UNIFORMS value is invalid." |
| << tcu::TestLog::EndMessage; |
| return ERROR; |
| } |
| if (!CheckMax(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, 0)) |
| { |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << "GL_MAX_FRAGMENT_IMAGE_UNIFORMS value is invalid." |
| << tcu::TestLog::EndMessage; |
| return ERROR; |
| } |
| if (!CheckMax(GL_MAX_COMBINED_IMAGE_UNIFORMS, 4)) |
| { |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << "GL_MAX_COMBINED_IMAGE_UNIFORMS value is invalid." |
| << tcu::TestLog::EndMessage; |
| return ERROR; |
| } |
| if (!CheckMax(GL_MAX_COMPUTE_IMAGE_UNIFORMS, 4)) |
| { |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << "GL_MAX_COMPUTE_IMAGE_UNIFORMS value is invalid." |
| << tcu::TestLog::EndMessage; |
| return ERROR; |
| } |
| return NO_ERROR; |
| } |
| }; |
| |
| //----------------------------------------------------------------------------- |
| // 1.1.2 BasicAPIBind |
| //----------------------------------------------------------------------------- |
| class BasicAPIBind : public ShaderImageLoadStoreBase |
| { |
| GLuint m_texture; |
| |
| virtual long Setup() |
| { |
| m_texture = 0; |
| return NO_ERROR; |
| } |
| |
| virtual long Run() |
| { |
| bool status = true; |
| for (GLuint index = 0; index < 4; ++index) |
| { |
| if (!CheckBinding(index, 0, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI)) |
| { |
| m_context.getTestContext().getLog() << tcu::TestLog::Message << "Binding point " << index |
| << " has invalid default state." << tcu::TestLog::EndMessage; |
| status = false; |
| } |
| } |
| |
| glGenTextures(1, &m_texture); |
| glBindTexture(GL_TEXTURE_2D_ARRAY, m_texture); |
| glTexStorage3D(GL_TEXTURE_2D_ARRAY, 4, GL_RG32F, 16, 16, 4); |
| glBindTexture(GL_TEXTURE_2D_ARRAY, 0); |
| |
| glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32F); |
| if (!CheckBinding(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32F)) |
| status = false; |
| |
| glBindImageTexture(3, m_texture, 1, GL_TRUE, 1, GL_WRITE_ONLY, GL_RGBA8); |
| if (!CheckBinding(3, m_texture, 1, GL_TRUE, 1, GL_WRITE_ONLY, GL_RGBA8)) |
| status = false; |
| |
| glBindImageTexture(1, m_texture, 3, GL_FALSE, 2, GL_READ_WRITE, GL_RGBA8UI); |
| if (!CheckBinding(1, m_texture, 3, GL_FALSE, 2, GL_READ_WRITE, GL_RGBA8UI)) |
| status = false; |
| |
| glBindImageTexture(2, m_texture, 4, GL_FALSE, 3, GL_READ_ONLY, GL_R32I); |
| if (!CheckBinding(2, m_texture, 4, GL_FALSE, 3, GL_READ_ONLY, GL_R32I)) |
| status = false; |
| |
| glDeleteTextures(1, &m_texture); |
| m_texture = 0; |
| |
| for (GLuint index = 0; index < 4; ++index) |
| { |
| GLint name; |
| glGetIntegeri_v(GL_IMAGE_BINDING_NAME, index, &name); |
| if (name != 0) |
| { |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << "Binding point " << index |
| << " should be set to 0 after texture deletion." << tcu::TestLog::EndMessage; |
| status = false; |
| } |
| if (!CheckBinding(index, 0, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI)) |
| status = false; |
| } |
| |
| return status ? NO_ERROR : ERROR; |
| } |
| |
| virtual long Cleanup() |
| { |
| glDeleteTextures(1, &m_texture); |
| return NO_ERROR; |
| } |
| }; |
| //----------------------------------------------------------------------------- |
| // 1.1.3 BasicAPIBarrier |
| //----------------------------------------------------------------------------- |
| class BasicAPIBarrier : public ShaderImageLoadStoreBase |
| { |
| virtual long Run() |
| { |
| glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT); |
| glMemoryBarrier(GL_ELEMENT_ARRAY_BARRIER_BIT); |
| glMemoryBarrier(GL_UNIFORM_BARRIER_BIT); |
| glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT); |
| glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); |
| glMemoryBarrier(GL_COMMAND_BARRIER_BIT); |
| glMemoryBarrier(GL_PIXEL_BUFFER_BARRIER_BIT); |
| glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT); |
| glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT); |
| glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT); |
| glMemoryBarrier(GL_TRANSFORM_FEEDBACK_BARRIER_BIT); |
| glMemoryBarrier(GL_ATOMIC_COUNTER_BARRIER_BIT); |
| glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT); |
| |
| glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT | GL_ELEMENT_ARRAY_BARRIER_BIT | GL_UNIFORM_BARRIER_BIT | |
| GL_TEXTURE_FETCH_BARRIER_BIT | GL_SHADER_IMAGE_ACCESS_BARRIER_BIT | GL_COMMAND_BARRIER_BIT | |
| GL_PIXEL_BUFFER_BARRIER_BIT | GL_TEXTURE_UPDATE_BARRIER_BIT | GL_BUFFER_UPDATE_BARRIER_BIT | |
| GL_FRAMEBUFFER_BARRIER_BIT | GL_TRANSFORM_FEEDBACK_BARRIER_BIT | GL_ATOMIC_COUNTER_BARRIER_BIT | |
| GL_SHADER_STORAGE_BARRIER_BIT); |
| |
| glMemoryBarrier(GL_ALL_BARRIER_BITS); |
| |
| return NO_ERROR; |
| } |
| }; |
| |
| class BasicAPIBarrierByRegion : public ShaderImageLoadStoreBase |
| { |
| virtual long Run() |
| { |
| glMemoryBarrierByRegion(GL_UNIFORM_BARRIER_BIT); |
| glMemoryBarrierByRegion(GL_TEXTURE_FETCH_BARRIER_BIT); |
| glMemoryBarrierByRegion(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); |
| glMemoryBarrierByRegion(GL_FRAMEBUFFER_BARRIER_BIT); |
| glMemoryBarrierByRegion(GL_ATOMIC_COUNTER_BARRIER_BIT); |
| glMemoryBarrierByRegion(GL_SHADER_STORAGE_BARRIER_BIT); |
| |
| glMemoryBarrierByRegion(GL_UNIFORM_BARRIER_BIT | GL_TEXTURE_FETCH_BARRIER_BIT | |
| GL_SHADER_IMAGE_ACCESS_BARRIER_BIT | GL_FRAMEBUFFER_BARRIER_BIT | |
| GL_ATOMIC_COUNTER_BARRIER_BIT | GL_SHADER_STORAGE_BARRIER_BIT); |
| |
| glMemoryBarrierByRegion(GL_ALL_BARRIER_BITS); |
| return NO_ERROR; |
| } |
| }; |
| //----------------------------------------------------------------------------- |
| // 1.1.4 BasicAPITexParam |
| //----------------------------------------------------------------------------- |
| class BasicAPITexParam : public ShaderImageLoadStoreBase |
| { |
| GLuint m_texture; |
| |
| virtual long Setup() |
| { |
| m_texture = 0; |
| return NO_ERROR; |
| } |
| |
| virtual long Run() |
| { |
| glGenTextures(1, &m_texture); |
| glBindTexture(GL_TEXTURE_2D, m_texture); |
| glTexStorage2D(GL_TEXTURE_2D, 5, GL_RG32F, 16, 16); |
| |
| GLint i; |
| GLfloat f; |
| |
| glGetTexParameteriv(GL_TEXTURE_2D, GL_IMAGE_FORMAT_COMPATIBILITY_TYPE, &i); |
| if (i != GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE) |
| { |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << "GL_IMAGE_FORMAT_COMPATIBILITY_TYPE should equal to " |
| << "GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE for textures allocated by the GL." |
| << tcu::TestLog::EndMessage; |
| return ERROR; |
| } |
| glGetTexParameterfv(GL_TEXTURE_2D, GL_IMAGE_FORMAT_COMPATIBILITY_TYPE, &f); |
| if (static_cast<GLenum>(f) != GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE) |
| { |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << "GL_IMAGE_FORMAT_COMPATIBILITY_TYPE should equal to " |
| << "GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE for textures allocated by the GL." |
| << tcu::TestLog::EndMessage; |
| return ERROR; |
| } |
| |
| return NO_ERROR; |
| } |
| |
| virtual long Cleanup() |
| { |
| glDeleteTextures(1, &m_texture); |
| return NO_ERROR; |
| } |
| }; |
| //----------------------------------------------------------------------------- |
| // 1.2.1 BasicAllFormatsStore |
| //----------------------------------------------------------------------------- |
| class BasicAllFormatsStoreFS : public ShaderImageLoadStoreBase |
| { |
| GLuint m_vao, m_vbo; |
| |
| virtual long Setup() |
| { |
| m_vao = 0; |
| m_vbo = 0; |
| return NO_ERROR; |
| } |
| |
| virtual long Run() |
| { |
| if (!IsVSFSAvailable(0, 1)) |
| return NOT_SUPPORTED; |
| |
| CreateFullViewportQuad(&m_vao, &m_vbo, NULL); |
| |
| if (!Write(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f))) |
| return ERROR; |
| if (!Write(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f))) |
| return ERROR; |
| if (!Write(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f))) |
| return ERROR; |
| |
| if (!Write(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4))) |
| return ERROR; |
| if (!Write(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1))) |
| return ERROR; |
| if (!Write(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4))) |
| return ERROR; |
| if (!Write(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4))) |
| return ERROR; |
| |
| if (!Write(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3))) |
| return ERROR; |
| if (!Write(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1))) |
| return ERROR; |
| if (!Write(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3))) |
| return ERROR; |
| if (!Write(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3))) |
| return ERROR; |
| |
| if (!Write(GL_RGBA8, vec4(1.0f), vec4(1.0f))) |
| return ERROR; |
| |
| if (!Write(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f))) |
| return ERROR; |
| |
| return NO_ERROR; |
| } |
| |
| template <typename T> |
| bool Write(GLenum internalformat, const T& write_value, const T& expected_value) |
| { |
| const char* src_vs = |
| NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL " gl_Position = i_position;" NL "}"; |
| GLuint program = BuildProgram(src_vs, GenFS(internalformat, write_value).c_str()); |
| const int kSize = 11; |
| std::vector<T> data(kSize * kSize); |
| GLuint texture; |
| glGenTextures(1, &texture); |
| glUseProgram(program); |
| |
| GLuint unit = 2; |
| glBindTexture(GL_TEXTURE_2D, texture); |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
| glTexStorage2D(GL_TEXTURE_2D, 1, internalformat, kSize, kSize); |
| glBindTexture(GL_TEXTURE_2D, 0); |
| |
| glViewport(0, 0, kSize, kSize); |
| glBindImageTexture(unit, texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat); |
| glBindVertexArray(m_vao); |
| glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); |
| |
| glBindTexture(GL_TEXTURE_2D, texture); |
| glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT); |
| |
| GLuint c_program = CreateComputeProgram(GenC(write_value)); |
| std::vector<T> out_data(kSize * kSize); |
| GLuint m_buffer; |
| glGenBuffers(1, &m_buffer); |
| glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer); |
| glBufferData(GL_SHADER_STORAGE_BUFFER, kSize * kSize * 4 * 4, &out_data[0], GL_STATIC_DRAW); |
| |
| glUseProgram(c_program); |
| glDispatchCompute(1, 1, 1); |
| glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT); |
| T* map_data = (T*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kSize * kSize * 4 * 4, GL_MAP_READ_BIT); |
| for (int i = 0; i < kSize * kSize; ++i) |
| { |
| if (!Equal(map_data[i], expected_value, internalformat)) |
| { |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << "[" << i << "] Value is: " << ToString(map_data[i]).c_str() |
| << ". Value should be: " << ToString(expected_value).c_str() |
| << ". Format is: " << FormatEnumToString(internalformat).c_str() << ". Unit is: " << unit << "." |
| << tcu::TestLog::EndMessage; |
| glDeleteTextures(1, &texture); |
| glUseProgram(0); |
| glDeleteProgram(program); |
| glDeleteProgram(c_program); |
| glDeleteBuffers(1, &m_buffer); |
| return false; |
| } |
| } |
| glDeleteTextures(1, &texture); |
| glUseProgram(0); |
| glDeleteProgram(program); |
| glDeleteProgram(c_program); |
| glDeleteBuffers(1, &m_buffer); |
| return true; |
| } |
| |
| virtual long Cleanup() |
| { |
| glViewport(0, 0, getWindowWidth(), getWindowHeight()); |
| glDeleteVertexArrays(1, &m_vao); |
| glDeleteBuffers(1, &m_vbo); |
| return NO_ERROR; |
| } |
| |
| template <typename T> |
| std::string GenFS(GLenum internalformat, const T& value) |
| { |
| std::ostringstream os; |
| os << NL "layout(" << FormatEnumToString(internalformat) << ", binding = 2) writeonly uniform " |
| << TypePrefix<T>() << "image2D g_image;" NL "void main() {" NL " ivec2 coord = ivec2(gl_FragCoord.xy);" NL |
| " imageStore(g_image, coord, " |
| << TypePrefix<T>() << "vec4" << value << ");" NL " discard;" NL "}"; |
| return os.str(); |
| } |
| |
| template <typename T> |
| std::string GenC(const T& value) |
| { |
| std::ostringstream os; |
| os << NL "#define KSIZE 11" NL "layout (local_size_x = KSIZE, local_size_y = KSIZE) in;" NL "uniform " |
| << TypePrefix<T>() << "sampler2D g_sampler;" NL "layout(std430) buffer OutputBuffer {" NL " " |
| << TypePrefix<T>() |
| << "vec4 data[KSIZE*KSIZE];" NL "};" NL "void main() {" NL |
| " data[gl_LocalInvocationIndex] = texelFetch(g_sampler, ivec2(gl_LocalInvocationID), 0);" NL |
| " //data[gl_LocalInvocationIndex] = " |
| << value << ";" NL "}"; |
| return os.str(); |
| } |
| }; |
| |
| class BasicAllFormatsStoreCS : public ShaderImageLoadStoreBase |
| { |
| virtual long Setup() |
| { |
| return NO_ERROR; |
| } |
| |
| template <typename T> |
| std::string GenCS(GLenum internalformat, const T& value) |
| { |
| std::ostringstream os; |
| os << NL "#define KSIZE 4" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform " |
| << TypePrefix<T>() |
| << "image2D g_image;" NL "layout (local_size_x = KSIZE, local_size_y = KSIZE) in;" NL "void main() {" NL |
| " ivec2 thread_xy = ivec2(gl_LocalInvocationID);" NL " imageStore(g_image, thread_xy, " |
| << TypePrefix<T>() << "vec4" << value << ");" NL "}"; |
| return os.str(); |
| } |
| |
| template <typename T> |
| std::string GenC(const T& value) |
| { |
| std::ostringstream os; |
| os << NL "#define KSIZE 4" NL "layout (local_size_x = KSIZE, local_size_y = KSIZE) in;" NL "uniform " |
| << TypePrefix<T>() << "sampler2D g_sampler;" NL "layout(std430) buffer OutputBuffer {" NL " " |
| << TypePrefix<T>() |
| << "vec4 data[KSIZE*KSIZE];" NL "};" NL "void main() {" NL |
| " data[gl_LocalInvocationIndex] = texelFetch(g_sampler, ivec2(gl_LocalInvocationID), 0);" NL |
| " //data[gl_LocalInvocationIndex] = " |
| << TypePrefix<T>() << "vec4" << value << ";" NL "}"; |
| return os.str(); |
| } |
| |
| template <typename T> |
| bool WriteCS(GLenum internalformat, const T& write_value, const T& expected_value) |
| { |
| const int kSize = 4; |
| GLuint program = CreateComputeProgram(GenCS(internalformat, write_value)); |
| |
| std::vector<T> data(kSize * kSize); |
| GLuint texture; |
| glGenTextures(1, &texture); |
| |
| GLuint unit = 0; |
| glBindTexture(GL_TEXTURE_2D, texture); |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
| glTexStorage2D(GL_TEXTURE_2D, 1, internalformat, kSize, kSize); |
| glBindTexture(GL_TEXTURE_2D, 0); |
| glBindImageTexture(unit, texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat); |
| glUseProgram(program); |
| glDispatchCompute(1, 1, 1); |
| |
| glBindTexture(GL_TEXTURE_2D, texture); |
| glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT); |
| |
| GLuint c_program = CreateComputeProgram(GenC(expected_value)); |
| std::vector<T> out_data(kSize * kSize); |
| GLuint m_buffer; |
| glGenBuffers(1, &m_buffer); |
| glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer); |
| glBufferData(GL_SHADER_STORAGE_BUFFER, kSize * kSize * 4 * 4, &out_data[0], GL_STATIC_DRAW); |
| |
| glUseProgram(c_program); |
| glDispatchCompute(1, 1, 1); |
| glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT); |
| T* map_data = (T*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kSize * kSize * 4 * 4, GL_MAP_READ_BIT); |
| for (int i = 0; i < kSize * kSize; ++i) |
| { |
| if (!Equal(map_data[i], expected_value, internalformat)) |
| { |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << "[" << i << "] Value is: " << ToString(map_data[i]).c_str() |
| << ". Value should be: " << ToString(expected_value).c_str() |
| << ". Format is: " << FormatEnumToString(internalformat).c_str() << ". Unit is: " << unit << "." |
| << tcu::TestLog::EndMessage; |
| glDeleteTextures(1, &texture); |
| glUseProgram(0); |
| glDeleteProgram(program); |
| glDeleteProgram(c_program); |
| glDeleteBuffers(1, &m_buffer); |
| return false; |
| } |
| } |
| glDeleteTextures(1, &texture); |
| glUseProgram(0); |
| glDeleteProgram(program); |
| glDeleteProgram(c_program); |
| glDeleteBuffers(1, &m_buffer); |
| |
| return true; |
| } |
| |
| virtual long Run() |
| { |
| |
| if (!WriteCS(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f))) |
| return ERROR; |
| if (!WriteCS(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f))) |
| return ERROR; |
| if (!WriteCS(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f))) |
| return ERROR; |
| |
| if (!WriteCS(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4))) |
| return ERROR; |
| if (!WriteCS(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1))) |
| return ERROR; |
| if (!WriteCS(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4))) |
| return ERROR; |
| if (!WriteCS(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4))) |
| return ERROR; |
| |
| if (!WriteCS(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3))) |
| return ERROR; |
| if (!WriteCS(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1))) |
| return ERROR; |
| if (!WriteCS(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3))) |
| return ERROR; |
| if (!WriteCS(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3))) |
| return ERROR; |
| |
| if (!WriteCS(GL_RGBA8, vec4(1.0f), vec4(1.0f))) |
| return ERROR; |
| |
| if (!WriteCS(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f))) |
| return ERROR; |
| |
| return NO_ERROR; |
| } |
| |
| virtual long Cleanup() |
| { |
| return NO_ERROR; |
| } |
| }; |
| //----------------------------------------------------------------------------- |
| // 1.2.2 BasicAllFormatsLoad |
| //----------------------------------------------------------------------------- |
| class BasicAllFormatsLoadFS : public ShaderImageLoadStoreBase |
| { |
| GLuint m_vao, m_vbo; |
| |
| virtual long Setup() |
| { |
| m_vao = 0; |
| m_vbo = 0; |
| return NO_ERROR; |
| } |
| |
| virtual long Run() |
| { |
| if (!IsVSFSAvailable(0, 1) || !IsSSBInVSFSAvailable(1)) |
| return NOT_SUPPORTED; |
| |
| CreateFullViewportQuad(&m_vao, &m_vbo, NULL); |
| |
| if (!Read(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f), GL_RGBA, GL_FLOAT)) |
| return ERROR; |
| if (!Read(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f), GL_RED, GL_FLOAT)) |
| return ERROR; |
| if (!Read(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f), GL_RGBA, GL_FLOAT)) |
| return ERROR; |
| |
| if (!Read(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4), GL_RGBA_INTEGER, GL_INT)) |
| return ERROR; |
| if (!Read(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1), GL_RED_INTEGER, GL_INT)) |
| return ERROR; |
| if (!Read(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4), GL_RGBA_INTEGER, GL_SHORT)) |
| return ERROR; |
| if (!Read(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4), GL_RGBA_INTEGER, GL_BYTE)) |
| return ERROR; |
| |
| if (!Read(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3), GL_RGBA_INTEGER, GL_UNSIGNED_INT)) |
| return ERROR; |
| if (!Read(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1), GL_RED_INTEGER, GL_UNSIGNED_INT)) |
| return ERROR; |
| if (!Read(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3), GL_RGBA_INTEGER, GL_UNSIGNED_SHORT)) |
| return ERROR; |
| if (!Read(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3), GL_RGBA_INTEGER, GL_UNSIGNED_BYTE)) |
| return ERROR; |
| |
| if (!Read(GL_RGBA8, vec4(1.0f), vec4(1.0f), GL_RGBA, GL_UNSIGNED_BYTE)) |
| return ERROR; |
| |
| if (!Read(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f), GL_RGBA, GL_BYTE)) |
| return ERROR; |
| |
| return NO_ERROR; |
| } |
| |
| template <typename T> |
| bool Read(GLenum internalformat, const T& value, const T& expected_value, GLenum format, GLenum type) |
| { |
| const char* src_vs = |
| NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL " gl_Position = i_position;" NL "}"; |
| GLuint program = BuildProgram(src_vs, GenFS(internalformat, expected_value).c_str()); |
| const int kSize = 11; |
| ShortByteData<T> d(kSize, value, internalformat, format); |
| GLuint texture; |
| glGenTextures(1, &texture); |
| GLuint unit = 1; |
| glBindTexture(GL_TEXTURE_2D, texture); |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
| glTexStorage2D(GL_TEXTURE_2D, 1, internalformat, kSize, kSize); |
| if (Shorts(internalformat)) |
| glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, format, type, &d.datas[0]); |
| else if (Bytes(internalformat)) |
| glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, format, type, &d.datab[0]); |
| else |
| glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, format, type, &d.data[0]); |
| glBindTexture(GL_TEXTURE_2D, 0); |
| |
| glViewport(0, 0, kSize, kSize); |
| glClear(GL_COLOR_BUFFER_BIT); |
| glUseProgram(program); |
| glBindImageTexture(unit, texture, 0, GL_FALSE, 0, GL_READ_ONLY, internalformat); |
| glBindVertexArray(m_vao); |
| |
| std::vector<T> out_data(kSize * kSize); |
| GLuint m_buffer; |
| glGenBuffers(1, &m_buffer); |
| glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer); |
| glBufferData(GL_SHADER_STORAGE_BUFFER, kSize * kSize * 4 * 4, &out_data[0], GL_STATIC_DRAW); |
| |
| glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); |
| glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT); |
| T* map_data = (T*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kSize * kSize * 4 * 4, GL_MAP_READ_BIT); |
| for (int i = 0; i < kSize * kSize; ++i) |
| { |
| if (!Equal(map_data[i], expected_value, internalformat)) |
| { |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << "[" << i << "] Value is: " << ToString(map_data[i]).c_str() |
| << ". Value should be: " << ToString(expected_value).c_str() |
| << ". Format is: " << FormatEnumToString(internalformat).c_str() << ". Unit is: " << unit << "." |
| << tcu::TestLog::EndMessage; |
| glUseProgram(0); |
| glDeleteProgram(program); |
| glDeleteTextures(1, &texture); |
| glDeleteBuffers(1, &m_buffer); |
| return false; |
| } |
| } |
| glUseProgram(0); |
| glDeleteProgram(program); |
| glDeleteTextures(1, &texture); |
| glDeleteBuffers(1, &m_buffer); |
| return true; |
| } |
| |
| virtual long Cleanup() |
| { |
| glViewport(0, 0, getWindowWidth(), getWindowHeight()); |
| glDeleteVertexArrays(1, &m_vao); |
| glDeleteBuffers(1, &m_vbo); |
| return NO_ERROR; |
| } |
| |
| template <typename T> |
| std::string GenFS(GLenum internalformat, const T& expected_value) |
| { |
| std::ostringstream os; |
| os << NL "#define KSIZE 11" NL "layout(" << FormatEnumToString(internalformat) |
| << ", binding = 1) readonly uniform " << TypePrefix<T>() |
| << "image2D g_image;" NL "layout(std430) buffer OutputBuffer {" NL " " << TypePrefix<T>() |
| << "vec4 data[KSIZE*KSIZE];" NL "};" NL "void main() {" NL " ivec2 coord = ivec2(gl_FragCoord.xy);" NL " " |
| << TypePrefix<T>() << "vec4 v = imageLoad(g_image, coord);" NL " data[coord.y * KSIZE + coord.x] = v;" NL |
| " //data[coord.y * KSIZE + coord.x] = " |
| << TypePrefix<T>() << "vec4" << expected_value << ";" NL " discard;" NL "}"; |
| return os.str(); |
| } |
| }; |
| |
| class BasicAllFormatsLoadCS : public ShaderImageLoadStoreBase |
| { |
| virtual long Setup() |
| { |
| return NO_ERROR; |
| } |
| |
| template <typename T> |
| std::string GenCS(GLenum internalformat, const T& expected_value) |
| { |
| std::ostringstream os; |
| os << NL "#define KSIZE 4" NL "layout (local_size_x = KSIZE, local_size_y = KSIZE) in;" NL "layout(" |
| << FormatEnumToString(internalformat) << ", binding = 1) readonly uniform " << TypePrefix<T>() |
| << "image2D g_image;" NL "layout(std430) buffer OutputBuffer {" NL " " << TypePrefix<T>() |
| << "vec4 data[KSIZE*KSIZE];" NL "};" NL "void main() {" NL " ivec2 coord = ivec2(gl_LocalInvocationID);" NL |
| " " |
| << TypePrefix<T>() << "vec4 v = imageLoad(g_image, coord);" NL " data[gl_LocalInvocationIndex] = v;" NL |
| " //data[gl_LocalInvocationIndex] = " |
| << TypePrefix<T>() << "vec4" << expected_value << ";" NL "}"; |
| return os.str(); |
| } |
| |
| virtual long Run() |
| { |
| if (!ReadCS(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f), GL_RGBA, GL_FLOAT)) |
| return ERROR; |
| if (!ReadCS(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f), GL_RED, GL_FLOAT)) |
| return ERROR; |
| if (!ReadCS(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f), GL_RGBA, GL_FLOAT)) |
| return ERROR; |
| |
| if (!ReadCS(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4), GL_RGBA_INTEGER, GL_INT)) |
| return ERROR; |
| if (!ReadCS(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1), GL_RED_INTEGER, GL_INT)) |
| return ERROR; |
| if (!ReadCS(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4), GL_RGBA_INTEGER, GL_SHORT)) |
| return ERROR; |
| if (!ReadCS(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4), GL_RGBA_INTEGER, GL_BYTE)) |
| return ERROR; |
| |
| if (!ReadCS(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3), GL_RGBA_INTEGER, GL_UNSIGNED_INT)) |
| return ERROR; |
| if (!ReadCS(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1), GL_RED_INTEGER, GL_UNSIGNED_INT)) |
| return ERROR; |
| if (!ReadCS(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3), GL_RGBA_INTEGER, GL_UNSIGNED_SHORT)) |
| return ERROR; |
| if (!ReadCS(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3), GL_RGBA_INTEGER, GL_UNSIGNED_BYTE)) |
| return ERROR; |
| |
| if (!ReadCS(GL_RGBA8, vec4(1.0f), vec4(1.0f), GL_RGBA, GL_UNSIGNED_BYTE)) |
| return ERROR; |
| |
| if (!ReadCS(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f), GL_RGBA, GL_BYTE)) |
| return ERROR; |
| |
| return NO_ERROR; |
| } |
| |
| template <typename T> |
| bool ReadCS(GLenum internalformat, const T& value, const T& expected_value, GLenum format, GLenum type) |
| { |
| GLuint program = CreateComputeProgram(GenCS(internalformat, expected_value)); |
| const int kSize = 4; |
| ShortByteData<T> d(kSize, value, internalformat, format); |
| GLuint texture; |
| glGenTextures(1, &texture); |
| |
| GLuint unit = 1; |
| glBindTexture(GL_TEXTURE_2D, texture); |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
| glTexStorage2D(GL_TEXTURE_2D, 1, internalformat, kSize, kSize); |
| if (Shorts(internalformat)) |
| glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, format, type, &d.datas[0]); |
| else if (Bytes(internalformat)) |
| glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, format, type, &d.datab[0]); |
| else |
| glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, format, type, &d.data[0]); |
| glBindTexture(GL_TEXTURE_2D, 0); |
| |
| glUseProgram(program); |
| glBindImageTexture(unit, texture, 0, GL_FALSE, 0, GL_READ_ONLY, internalformat); |
| |
| std::vector<T> out_data(kSize * kSize); |
| GLuint m_buffer; |
| glGenBuffers(1, &m_buffer); |
| glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer); |
| glBufferData(GL_SHADER_STORAGE_BUFFER, kSize * kSize * 4 * 4, &out_data[0], GL_STATIC_DRAW); |
| |
| glDispatchCompute(1, 1, 1); |
| glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT); |
| T* map_data = (T*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kSize * kSize * 4 * 4, GL_MAP_READ_BIT); |
| for (int i = 0; i < kSize * kSize; ++i) |
| { |
| if (!Equal(map_data[i], expected_value, internalformat)) |
| { |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << "[" << i << "] Value is: " << ToString(map_data[i]).c_str() |
| << ". Value should be: " << ToString(expected_value).c_str() |
| << ". Format is: " << FormatEnumToString(internalformat).c_str() << ". Unit is: " << unit << "." |
| << tcu::TestLog::EndMessage; |
| glUseProgram(0); |
| glDeleteProgram(program); |
| glDeleteTextures(1, &texture); |
| glDeleteBuffers(1, &m_buffer); |
| return false; |
| } |
| } |
| glUseProgram(0); |
| glDeleteProgram(program); |
| glDeleteTextures(1, &texture); |
| glDeleteBuffers(1, &m_buffer); |
| return true; |
| } |
| |
| virtual long Cleanup() |
| { |
| return NO_ERROR; |
| } |
| }; |
| |
| class BasicAllFormatsLoadStoreComputeStage : public ShaderImageLoadStoreBase |
| { |
| virtual long Run() |
| { |
| |
| if (!Read(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(2.0f, 4.0f, 6.0f, 8.0f), GL_RGBA, GL_FLOAT)) |
| return ERROR; |
| if (!Read(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(2.0f, 0.0f, 0.0f, 1.0f), GL_RED, GL_FLOAT)) |
| return ERROR; |
| if (!Read(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(2.0f, 4.0f, 6.0f, 8.0f), GL_RGBA, GL_FLOAT)) |
| return ERROR; |
| |
| if (!Read(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(2, -4, 6, -8), GL_RGBA_INTEGER, GL_INT)) |
| return ERROR; |
| if (!Read(GL_R32I, ivec4(1, -2, 3, -4), ivec4(2, 0, 0, 1), GL_RED_INTEGER, GL_INT)) |
| return ERROR; |
| if (!Read(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(2, -4, 6, -8), GL_RGBA_INTEGER, GL_SHORT)) |
| return ERROR; |
| if (!Read(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(2, -4, 6, -8), GL_RGBA_INTEGER, GL_BYTE)) |
| return ERROR; |
| |
| if (!Read(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 2, 4, 6), GL_RGBA_INTEGER, GL_UNSIGNED_INT)) |
| return ERROR; |
| if (!Read(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(14, 0, 0, 1), GL_RED_INTEGER, GL_UNSIGNED_INT)) |
| return ERROR; |
| if (!Read(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 2, 4, 6), GL_RGBA_INTEGER, GL_UNSIGNED_SHORT)) |
| return ERROR; |
| if (!Read(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 2, 4, 6), GL_RGBA_INTEGER, GL_UNSIGNED_BYTE)) |
| return ERROR; |
| |
| if (!Read(GL_RGBA8, vec4(0.5f), vec4(1.0f), GL_RGBA, GL_UNSIGNED_BYTE)) |
| return ERROR; |
| if (!Read(GL_RGBA8_SNORM, vec4(0.5f, 0.0f, 0.5f, -0.5f), vec4(1.0f, 0.0f, 1.0f, -1.0f), GL_RGBA, GL_BYTE)) |
| return ERROR; |
| |
| return NO_ERROR; |
| } |
| |
| template <typename T> |
| bool Read(GLenum internalformat, const T& value, const T& expected_value, GLenum format, GLenum type) |
| { |
| GLuint program = CreateComputeProgram(GenCS(internalformat, expected_value)); |
| |
| const int kSize = 8; |
| ShortByteData<T> d(kSize, value, internalformat, format); |
| GLuint texture[2]; |
| glGenTextures(2, texture); |
| |
| /* read texture */ |
| { |
| glBindTexture(GL_TEXTURE_2D, texture[0]); |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
| glTexStorage2D(GL_TEXTURE_2D, 1, internalformat, kSize, kSize); |
| if (Shorts(internalformat)) |
| glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, format, type, &d.datas[0]); |
| else if (Bytes(internalformat)) |
| glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, format, type, &d.datab[0]); |
| else |
| glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, format, type, &d.data[0]); |
| } |
| /* write texture */ |
| { |
| glBindTexture(GL_TEXTURE_2D, texture[1]); |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
| glTexStorage2D(GL_TEXTURE_2D, 1, internalformat, kSize, kSize); |
| } |
| glBindTexture(GL_TEXTURE_2D, 0); |
| |
| glUseProgram(program); |
| |
| glBindImageTexture(2, texture[0], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat); |
| glBindImageTexture(3, texture[1], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat); |
| |
| glDispatchCompute(1, 1, 1); |
| |
| glBindTexture(GL_TEXTURE_2D, texture[1]); |
| glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT); |
| |
| GLuint c_program = CreateComputeProgram(GenC(expected_value)); |
| std::vector<T> out_data(kSize * kSize); |
| GLuint m_buffer; |
| glGenBuffers(1, &m_buffer); |
| glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer); |
| glBufferData(GL_SHADER_STORAGE_BUFFER, kSize * kSize * 4 * 4, &out_data[0], GL_STATIC_DRAW); |
| |
| glUseProgram(c_program); |
| glDispatchCompute(1, 1, 1); |
| glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT); |
| T* map_data = (T*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kSize * kSize * 4 * 4, GL_MAP_READ_BIT); |
| for (int i = 0; i < kSize * kSize; ++i) |
| { |
| if (!Equal(map_data[i], expected_value, internalformat)) |
| { |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << "[" << i << "] Value is: " << ToString(map_data[i]).c_str() |
| << ". Value should be: " << ToString(expected_value).c_str() |
| << ". Format is: " << FormatEnumToString(internalformat).c_str() << "." << tcu::TestLog::EndMessage; |
| glDeleteTextures(2, texture); |
| glUseProgram(0); |
| glDeleteProgram(program); |
| glDeleteProgram(c_program); |
| glDeleteBuffers(1, &m_buffer); |
| return false; |
| } |
| } |
| glDeleteTextures(2, texture); |
| glUseProgram(0); |
| glDeleteProgram(program); |
| glDeleteProgram(c_program); |
| glDeleteBuffers(1, &m_buffer); |
| |
| return true; |
| } |
| |
| template <typename T> |
| std::string GenCS(GLenum internalformat, const T& expected_value) |
| { |
| std::ostringstream os; |
| os << NL "#define KSIZE 8" NL "layout(local_size_x = KSIZE, local_size_y = KSIZE) in;" NL "layout(" |
| << FormatEnumToString(internalformat) << ", binding = 2) readonly uniform " << TypePrefix<T>() |
| << "image2D g_image_read;" NL "layout(" << FormatEnumToString(internalformat) |
| << ", binding = 3) writeonly uniform " << TypePrefix<T>() |
| << "image2D g_image_write;" NL "void main() {" NL " ivec2 coord = ivec2(gl_LocalInvocationID);" NL " " |
| << TypePrefix<T>() << "vec4 v = imageLoad(g_image_read, coord);" NL |
| " imageStore(g_image_write, coord, v+v);" NL " //imageStore(g_image_write, coord, " |
| << TypePrefix<T>() << "vec4" << expected_value << ");" NL "}"; |
| return os.str(); |
| } |
| |
| template <typename T> |
| std::string GenC(const T& value) |
| { |
| std::ostringstream os; |
| os << NL "#define KSIZE 8" NL "layout (local_size_x = KSIZE, local_size_y = KSIZE) in;" NL "uniform " |
| << TypePrefix<T>() << "sampler2D g_sampler;" NL "layout(std430) buffer OutputBuffer {" NL " " |
| << TypePrefix<T>() |
| << "vec4 data[KSIZE*KSIZE];" NL "};" NL "void main() {" NL |
| " data[gl_LocalInvocationIndex] = texelFetch(g_sampler, ivec2(gl_LocalInvocationID), 0);" NL |
| " //data[gl_LocalInvocationIndex] = " |
| << TypePrefix<T>() << "vec4" << value << ";" NL "}"; |
| return os.str(); |
| } |
| }; |
| //----------------------------------------------------------------------------- |
| // 1.3.1 BasicAllTargetsStore |
| //----------------------------------------------------------------------------- |
| class BasicAllTargetsStoreFS : public ShaderImageLoadStoreBase |
| { |
| GLuint m_vao; |
| GLuint m_vbo; |
| |
| virtual long Setup() |
| { |
| m_vao = 0; |
| m_vbo = 0; |
| return NO_ERROR; |
| } |
| |
| virtual long Run() |
| { |
| if (!IsVSFSAvailable(0, 4)) |
| return NOT_SUPPORTED; |
| CreateFullViewportQuad(&m_vao, &m_vbo, NULL); |
| |
| if (!Write(T2D, GL_RGBA32F, vec4(-1.0f, 2.0f, 3.0f, -4.0f), vec4(-1.0f, 2.0f, 3.0f, -4.0f))) |
| return ERROR; |
| if (!Write(T2D, GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4))) |
| return ERROR; |
| if (!Write(T2D, GL_RGBA32UI, uvec4(1, 2, 3, 4), uvec4(1, 2, 3, 4))) |
| return ERROR; |
| if (!Write(T3D, GL_RGBA32F, vec4(-1.0f, 2.0f, 3.0f, -4.0f), vec4(-1.0f, 2.0f, 3.0f, -4.0f))) |
| return ERROR; |
| if (!Write(T3D, GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4))) |
| return ERROR; |
| if (!Write(T3D, GL_RGBA32UI, uvec4(1, 2, 3, 4), uvec4(1, 2, 3, 4))) |
| return ERROR; |
| if (!Write(TCM, GL_RGBA32F, vec4(-1.0f, 2.0f, 3.0f, -4.0f), vec4(-1.0f, 2.0f, 3.0f, -4.0f))) |
| return ERROR; |
| if (!Write(TCM, GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4))) |
| return ERROR; |
| if (!Write(TCM, GL_RGBA32UI, uvec4(1, 2, 3, 4), uvec4(1, 2, 3, 4))) |
| return ERROR; |
| if (!Write(T2DA, GL_RGBA32F, vec4(-1.0f, 2.0f, 3.0f, -4.0f), vec4(-1.0f, 2.0f, 3.0f, -4.0f))) |
| return ERROR; |
| if (!Write(T2DA, GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4))) |
| return ERROR; |
| if (!Write(T2DA, GL_RGBA32UI, uvec4(1, 2, 3, 4), uvec4(1, 2, 3, 4))) |
| return ERROR; |
| |
| return NO_ERROR; |
| } |
| |
| virtual long Cleanup() |
| { |
| glViewport(0, 0, getWindowWidth(), getWindowHeight()); |
| glDeleteVertexArrays(1, &m_vao); |
| glDeleteBuffers(1, &m_vbo); |
| glActiveTexture(GL_TEXTURE0); |
| return NO_ERROR; |
| } |
| |
| template <typename T> |
| bool Write(int target, GLenum internalformat, const T& write_value, const T& expected_value) |
| { |
| const char* src_vs = |
| NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL " gl_Position = i_position;" NL "}"; |
| const GLuint program = BuildProgram(src_vs, GenFS(target, internalformat, write_value).c_str()); |
| GLuint textures[8]; |
| glGenTextures(8, textures); |
| |
| const int kSize = 11; |
| std::vector<T> data(kSize * kSize * 2); |
| |
| glBindTexture(GL_TEXTURE_2D, textures[1]); |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
| glTexStorage2D(GL_TEXTURE_2D, 1, internalformat, kSize, kSize); |
| glBindTexture(GL_TEXTURE_2D, 0); |
| |
| glBindTexture(GL_TEXTURE_3D, textures[2]); |
| glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
| glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
| glTexStorage3D(GL_TEXTURE_3D, 1, internalformat, kSize, kSize, 2); |
| glBindTexture(GL_TEXTURE_3D, 0); |
| |
| glBindTexture(GL_TEXTURE_CUBE_MAP, textures[4]); |
| glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
| glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
| glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, internalformat, kSize, kSize); |
| glBindTexture(GL_TEXTURE_CUBE_MAP, 0); |
| |
| glBindTexture(GL_TEXTURE_2D_ARRAY, textures[7]); |
| glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
| glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
| glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, internalformat, kSize, kSize, 2); |
| glBindTexture(GL_TEXTURE_2D_ARRAY, 0); |
| |
| glBindImageTexture(0, textures[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat); // 2D |
| glBindImageTexture(1, textures[2], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat); // 3D |
| glBindImageTexture(2, textures[4], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat); // Cube |
| glBindImageTexture(3, textures[7], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat); // 2DArray |
| |
| glUseProgram(program); |
| glBindVertexArray(m_vao); |
| glViewport(0, 0, kSize, kSize); |
| glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); |
| |
| glActiveTexture(GL_TEXTURE1); |
| glBindTexture(GL_TEXTURE_2D, textures[1]); |
| glActiveTexture(GL_TEXTURE2); |
| glBindTexture(GL_TEXTURE_3D, textures[2]); |
| glActiveTexture(GL_TEXTURE3); |
| glBindTexture(GL_TEXTURE_CUBE_MAP, textures[4]); |
| glActiveTexture(GL_TEXTURE4); |
| glBindTexture(GL_TEXTURE_2D_ARRAY, textures[7]); |
| glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT); |
| |
| GLuint c_program = CreateComputeProgram(GenC(write_value)); |
| std::vector<T> out_data2D(kSize * kSize * 6); |
| std::vector<T> out_data3D(kSize * kSize * 6); |
| std::vector<T> out_dataCube(kSize * kSize * 6); |
| std::vector<T> out_data2DArray(kSize * kSize * 6); |
| GLuint m_buffer[4]; |
| glGenBuffers(4, m_buffer); |
| glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_buffer[0]); |
| glBufferData(GL_SHADER_STORAGE_BUFFER, 6 * kSize * kSize * 4 * 4, &out_dataCube[0], GL_STATIC_DRAW); |
| glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer[1]); |
| glBufferData(GL_SHADER_STORAGE_BUFFER, 6 * kSize * kSize * 4 * 4, &out_dataCube[0], GL_STATIC_DRAW); |
| glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_buffer[2]); |
| glBufferData(GL_SHADER_STORAGE_BUFFER, 6 * kSize * kSize * 4 * 4, &out_dataCube[0], GL_STATIC_DRAW); |
| glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_buffer[3]); |
| glBufferData(GL_SHADER_STORAGE_BUFFER, 6 * kSize * kSize * 4 * 4, &out_dataCube[0], GL_STATIC_DRAW); |
| |
| glUseProgram(c_program); |
| glUniform1i(glGetUniformLocation(c_program, "g_sampler_2d"), 1); |
| glUniform1i(glGetUniformLocation(c_program, "g_sampler_3d"), 2); |
| glUniform1i(glGetUniformLocation(c_program, "g_sampler_cube"), 3); |
| glUniform1i(glGetUniformLocation(c_program, "g_sampler_2darray"), 4); |
| glDispatchCompute(1, 1, 1); |
| glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT); |
| |
| bool status = true; |
| glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer[target]); |
| T* map_data = (T*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 6 * kSize * kSize * 4 * 4, GL_MAP_READ_BIT); |
| int layers = 2; |
| if (target == T2D) |
| layers = 1; |
| if (target == TCM) |
| layers = 6; |
| status = CompareValues(map_data, kSize, expected_value, internalformat, layers); |
| if (!status) |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << target << " target, " << FormatEnumToString(internalformat).c_str() |
| << " format failed." << tcu::TestLog::EndMessage; |
| glUnmapBuffer(GL_SHADER_STORAGE_BUFFER); |
| |
| glDeleteTextures(8, textures); |
| glUseProgram(0); |
| glDeleteProgram(program); |
| glDeleteProgram(c_program); |
| glDeleteBuffers(4, m_buffer); |
| |
| return status; |
| } |
| |
| template <typename T> |
| std::string GenFS(int target, GLenum internalformat, const T& write_value) |
| { |
| std::ostringstream os; |
| switch (target) |
| { |
| case T2D: |
| os << NL "layout(" << FormatEnumToString(internalformat) << ", binding = 0) writeonly uniform " |
| << TypePrefix<T>() << "image2D g_image_2d;"; |
| break; |
| case T3D: |
| os << NL "layout(" << FormatEnumToString(internalformat) << ", binding = 1) writeonly uniform " |
| << TypePrefix<T>() << "image3D g_image_3d;"; |
| break; |
| case TCM: |
| os << NL "layout(" << FormatEnumToString(internalformat) << ", binding = 2) writeonly uniform " |
| << TypePrefix<T>() << "imageCube g_image_cube;"; |
| break; |
| case T2DA: |
| os << NL "layout(" << FormatEnumToString(internalformat) << ", binding = 3) writeonly uniform " |
| << TypePrefix<T>() << "image2DArray g_image_2darray;"; |
| break; |
| } |
| os << NL "void main() {" NL " ivec2 coord = ivec2(gl_FragCoord.xy);"; |
| |
| switch (target) |
| { |
| case T2D: |
| os << NL " imageStore(g_image_2d, coord, " << TypePrefix<T>() << "vec4" << write_value << ");"; |
| break; |
| case T3D: |
| os << NL " imageStore(g_image_3d, ivec3(coord, 0), " << TypePrefix<T>() << "vec4" << write_value |
| << ");" NL " imageStore(g_image_3d, ivec3(coord, 1), " << TypePrefix<T>() << "vec4" << write_value |
| << ");"; |
| break; |
| case TCM: |
| os << NL " imageStore(g_image_cube, ivec3(coord, 0), " << TypePrefix<T>() << "vec4" << write_value |
| << ");" NL " imageStore(g_image_cube, ivec3(coord, 1), " << TypePrefix<T>() << "vec4" << write_value |
| << ");" NL " imageStore(g_image_cube, ivec3(coord, 2), " << TypePrefix<T>() << "vec4" << write_value |
| << ");" NL " imageStore(g_image_cube, ivec3(coord, 3), " << TypePrefix<T>() << "vec4" << write_value |
| << ");" NL " imageStore(g_image_cube, ivec3(coord, 4), " << TypePrefix<T>() << "vec4" << write_value |
| << ");" NL " imageStore(g_image_cube, ivec3(coord, 5), " << TypePrefix<T>() << "vec4" << write_value |
| << ");"; |
| break; |
| case T2DA: |
| os << NL " imageStore(g_image_2darray, ivec3(coord, 0), " << TypePrefix<T>() << "vec4" << write_value |
| << ");" NL " imageStore(g_image_2darray, ivec3(coord, 1), " << TypePrefix<T>() << "vec4" << write_value |
| << ");"; |
| break; |
| } |
| os << NL " discard;" NL "}"; |
| return os.str(); |
| } |
| |
| template <typename T> |
| std::string GenC(const T& write_value) |
| { |
| std::ostringstream os; |
| os << NL "#define KSIZE 11" NL "layout (local_size_x = KSIZE, local_size_y = KSIZE) in;" NL "uniform " |
| << TypePrefix<T>() << "sampler2D g_sampler_2d;" NL "uniform " << TypePrefix<T>() |
| << "sampler3D g_sampler_3d;" NL "uniform " << TypePrefix<T>() << "samplerCube g_sampler_cube;" NL "uniform " |
| << TypePrefix<T>() |
| << "sampler2DArray g_sampler_2darray;" NL "layout(std430, binding = 1) buffer OutputBuffer2D {" NL " " |
| << TypePrefix<T>() << "vec4 data[KSIZE*KSIZE];" NL "} g_buff_2d;" NL |
| "layout(std430, binding = 0) buffer OutputBuffer3D {" NL " " |
| << TypePrefix<T>() << "vec4 data[KSIZE*KSIZE*2];" NL "} g_buff_3d;" NL |
| "layout(std430, binding = 3) buffer OutputBufferCube {" NL " " |
| << TypePrefix<T>() << "vec4 data[KSIZE*KSIZE*6];" NL "} g_buff_cube;" NL |
| "layout(std430, binding = 2) buffer OutputBuffer2DArray {" NL " " |
| << TypePrefix<T>() |
| << "vec4 data[KSIZE*KSIZE*2];" NL "} g_buff_2darray;" NL "void main() {" NL |
| " int cubemap_i = 2 * int(gl_LocalInvocationID.x) - KSIZE + 1;" NL |
| " int cubemap_j = 2 * int(gl_LocalInvocationID.y) - KSIZE + 1;" NL |
| " uint layer = uint(KSIZE * KSIZE);" NL |
| " g_buff_2d.data[gl_LocalInvocationIndex] = texelFetch(g_sampler_2d, ivec2(gl_LocalInvocationID), 0);" NL |
| " g_buff_3d.data[gl_LocalInvocationIndex] = texelFetch(g_sampler_3d, ivec3(gl_LocalInvocationID.xy, 0), " |
| "0);" NL " g_buff_3d.data[gl_LocalInvocationIndex + layer] = texelFetch(g_sampler_3d, " |
| "ivec3(gl_LocalInvocationID.xy, 1), 0);" NL " g_buff_2darray.data[gl_LocalInvocationIndex] = " |
| "texelFetch(g_sampler_2darray, " |
| "ivec3(gl_LocalInvocationID.xy, 0), 0);" NL |
| " g_buff_2darray.data[gl_LocalInvocationIndex + layer] = texelFetch(g_sampler_2darray, " |
| "ivec3(gl_LocalInvocationID.xy, 1), 0);" NL " g_buff_cube.data[gl_LocalInvocationIndex] = " |
| "texture(g_sampler_cube, vec3(KSIZE,cubemap_i,cubemap_j));" NL |
| " g_buff_cube.data[gl_LocalInvocationIndex + layer] = texture(g_sampler_cube, " |
| "vec3(KSIZE,cubemap_i,cubemap_j));" NL " g_buff_cube.data[gl_LocalInvocationIndex + 2u * layer] = " |
| "texture(g_sampler_cube, vec3(cubemap_i,KSIZE,cubemap_j));" NL |
| " g_buff_cube.data[gl_LocalInvocationIndex + 3u * layer] = texture(g_sampler_cube, " |
| "vec3(cubemap_i,KSIZE,cubemap_j));" NL " g_buff_cube.data[gl_LocalInvocationIndex + 4u * layer] = " |
| "texture(g_sampler_cube, vec3(cubemap_i,cubemap_j,KSIZE));" NL |
| " g_buff_cube.data[gl_LocalInvocationIndex + 5u * layer] = texture(g_sampler_cube, " |
| "vec3(cubemap_i,cubemap_j,KSIZE));" NL " //g_buff_2d.data[gl_LocalInvocationIndex] = " |
| << write_value << ";" NL "}"; |
| return os.str(); |
| } |
| }; |
| |
| class BasicAllTargetsStoreCS : public ShaderImageLoadStoreBase |
| { |
| virtual long Setup() |
| { |
| return NO_ERROR; |
| } |
| |
| virtual long Run() |
| { |
| |
| if (!Write(T2D, GL_RGBA32F, vec4(-1.0f, 2.0f, 3.0f, -4.0f), vec4(-1.0f, 2.0f, 3.0f, -4.0f))) |
| return ERROR; |
| if (!Write(T2D, GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4))) |
| return ERROR; |
| if (!Write(T2D, GL_RGBA32UI, uvec4(1, 2, 3, 4), uvec4(1, 2, 3, 4))) |
| return ERROR; |
| if (!Write(T3D, GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4))) |
| return ERROR; |
| if (!Write(T3D, GL_RGBA32UI, uvec4(1, 2, 3, 4), uvec4(1, 2, 3, 4))) |
| return ERROR; |
| if (!Write(T3D, GL_RGBA32F, vec4(-1.0f, 2.0f, 3.0f, -4.0f), vec4(-1.0f, 2.0f, 3.0f, -4.0f))) |
| return ERROR; |
| if (!Write(TCM, GL_RGBA32UI, uvec4(1, 2, 3, 4), uvec4(1, 2, 3, 4))) |
| return ERROR; |
| if (!Write(TCM, GL_RGBA32F, vec4(-1.0f, 2.0f, 3.0f, -4.0f), vec4(-1.0f, 2.0f, 3.0f, -4.0f))) |
| return ERROR; |
| if (!Write(TCM, GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4))) |
| return ERROR; |
| if (!Write(T2DA, GL_RGBA32F, vec4(-1.0f, 2.0f, 3.0f, -4.0f), vec4(-1.0f, 2.0f, 3.0f, -4.0f))) |
| return ERROR; |
| if (!Write(T2DA, GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4))) |
| return ERROR; |
| if (!Write(T2DA, GL_RGBA32UI, uvec4(1, 2, 3, 4), uvec4(1, 2, 3, 4))) |
| return ERROR; |
| |
| return NO_ERROR; |
| } |
| |
| virtual long Cleanup() |
| { |
| glActiveTexture(GL_TEXTURE0); |
| return NO_ERROR; |
| } |
| |
| template <typename T> |
| bool Write(int target, GLenum internalformat, const T& write_value, const T& expected_value) |
| { |
| const GLuint program = CreateComputeProgram(GenCS(target, internalformat, write_value)); |
| GLuint textures[8]; |
| glGenTextures(8, textures); |
| |
| const int kSize = 11; |
| std::vector<T> data(kSize * kSize * 2); |
| |
| glBindTexture(GL_TEXTURE_2D, textures[1]); |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
| glTexStorage2D(GL_TEXTURE_2D, 1, internalformat, kSize, kSize); |
| glBindTexture(GL_TEXTURE_2D, 0); |
| |
| glBindTexture(GL_TEXTURE_3D, textures[2]); |
| glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
| glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
| glTexStorage3D(GL_TEXTURE_3D, 1, internalformat, kSize, kSize, 2); |
| glBindTexture(GL_TEXTURE_3D, 0); |
| |
| glBindTexture(GL_TEXTURE_CUBE_MAP, textures[4]); |
| glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
| glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
| glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, internalformat, kSize, kSize); |
| glBindTexture(GL_TEXTURE_CUBE_MAP, 0); |
| |
| glBindTexture(GL_TEXTURE_2D_ARRAY, textures[7]); |
| glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
| glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
| glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, internalformat, kSize, kSize, 2); |
| glBindTexture(GL_TEXTURE_2D_ARRAY, 0); |
| |
| glBindImageTexture(0, textures[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat); // 2D |
| glBindImageTexture(1, textures[2], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat); // 3D |
| glBindImageTexture(2, textures[4], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat); // Cube |
| glBindImageTexture(3, textures[7], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat); // 2DArray |
| |
| glUseProgram(program); |
| glDispatchCompute(1, 1, 1); |
| |
| glActiveTexture(GL_TEXTURE1); |
| glBindTexture(GL_TEXTURE_2D, textures[1]); |
| glActiveTexture(GL_TEXTURE2); |
| glBindTexture(GL_TEXTURE_3D, textures[2]); |
| glActiveTexture(GL_TEXTURE3); |
| glBindTexture(GL_TEXTURE_CUBE_MAP, textures[4]); |
| glActiveTexture(GL_TEXTURE4); |
| glBindTexture(GL_TEXTURE_2D_ARRAY, textures[7]); |
| glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT); |
| |
| GLuint c_program = CreateComputeProgram(GenC(write_value)); |
| std::vector<T> out_data2D(kSize * kSize * 6); |
| std::vector<T> out_data3D(kSize * kSize * 6); |
| std::vector<T> out_dataCube(kSize * kSize * 6); |
| std::vector<T> out_data2DArray(kSize * kSize * 6); |
| GLuint m_buffer[4]; |
| glGenBuffers(4, m_buffer); |
| glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer[0]); |
| glBufferData(GL_SHADER_STORAGE_BUFFER, 6 * kSize * kSize * 4 * 4, &out_dataCube[0], GL_STATIC_DRAW); |
| glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_buffer[1]); |
| glBufferData(GL_SHADER_STORAGE_BUFFER, 6 * kSize * kSize * 4 * 4, &out_dataCube[0], GL_STATIC_DRAW); |
| glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_buffer[2]); |
| glBufferData(GL_SHADER_STORAGE_BUFFER, 6 * kSize * kSize * 4 * 4, &out_dataCube[0], GL_STATIC_DRAW); |
| glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_buffer[3]); |
| glBufferData(GL_SHADER_STORAGE_BUFFER, 6 * kSize * kSize * 4 * 4, &out_dataCube[0], GL_STATIC_DRAW); |
| |
| glUseProgram(c_program); |
| glUniform1i(glGetUniformLocation(c_program, "g_sampler_2d"), 1); |
| glUniform1i(glGetUniformLocation(c_program, "g_sampler_3d"), 2); |
| glUniform1i(glGetUniformLocation(c_program, "g_sampler_cube"), 3); |
| glUniform1i(glGetUniformLocation(c_program, "g_sampler_2darray"), 4); |
| |
| glDispatchCompute(1, 1, 1); |
| glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT); |
| |
| bool status = true; |
| |
| glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer[target]); |
| T* map_data = (T*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 6 * kSize * kSize * 4 * 4, GL_MAP_READ_BIT); |
| int layers = 2; |
| if (target == T2D) |
| layers = 1; |
| if (target == TCM) |
| layers = 6; |
| status = CompareValues(map_data, kSize, expected_value, internalformat, layers); |
| if (!status) |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << target << " target, " << FormatEnumToString(internalformat).c_str() |
| << " format failed." << tcu::TestLog::EndMessage; |
| glUnmapBuffer(GL_SHADER_STORAGE_BUFFER); |
| |
| glDeleteTextures(8, textures); |
| glUseProgram(0); |
| glDeleteProgram(program); |
| glDeleteProgram(c_program); |
| glDeleteBuffers(4, m_buffer); |
| |
| return status; |
| } |
| |
| template <typename T> |
| std::string GenCS(int target, GLenum internalformat, const T& write_value) |
| { |
| std::ostringstream os; |
| os << NL "#define KSIZE 11" NL "layout (local_size_x = KSIZE, local_size_y = KSIZE) in;"; |
| switch (target) |
| { |
| case T2D: |
| os << NL "layout(" << FormatEnumToString(internalformat) << ", binding = 0) writeonly uniform " |
| << TypePrefix<T>() << "image2D g_image_2d;"; |
| break; |
| case T3D: |
| os << NL "layout(" << FormatEnumToString(internalformat) << ", binding = 1) writeonly uniform " |
| << TypePrefix<T>() << "image3D g_image_3d;"; |
| break; |
| case TCM: |
| os << NL "layout(" << FormatEnumToString(internalformat) << ", binding = 2) writeonly uniform " |
| << TypePrefix<T>() << "imageCube g_image_cube;"; |
| break; |
| case T2DA: |
| os << NL "layout(" << FormatEnumToString(internalformat) << ", binding = 3) writeonly uniform " |
| << TypePrefix<T>() << "image2DArray g_image_2darray;"; |
| break; |
| } |
| os << NL "void main() {" NL " ivec2 coord = ivec2(gl_LocalInvocationID);"; |
| switch (target) |
| { |
| case T2D: |
| os << NL " imageStore(g_image_2d, coord, " << TypePrefix<T>() << "vec4" << write_value << ");"; |
| break; |
| case T3D: |
| os << NL " imageStore(g_image_3d, ivec3(coord, 0), " << TypePrefix<T>() << "vec4" << write_value |
| << ");" NL " imageStore(g_image_3d, ivec3(coord, 1), " << TypePrefix<T>() << "vec4" << write_value |
| << ");"; |
| break; |
| case TCM: |
| os << NL " imageStore(g_image_cube, ivec3(coord, 0), " << TypePrefix<T>() << "vec4" << write_value |
| << ");" NL " imageStore(g_image_cube, ivec3(coord, 1), " << TypePrefix<T>() << "vec4" << write_value |
| << ");" NL " imageStore(g_image_cube, ivec3(coord, 2), " << TypePrefix<T>() << "vec4" << write_value |
| << ");" NL " imageStore(g_image_cube, ivec3(coord, 3), " << TypePrefix<T>() << "vec4" << write_value |
| << ");" NL " imageStore(g_image_cube, ivec3(coord, 4), " << TypePrefix<T>() << "vec4" << write_value |
| << ");" NL " imageStore(g_image_cube, ivec3(coord, 5), " << TypePrefix<T>() << "vec4" << write_value |
| << ");"; |
| break; |
| case T2DA: |
| os << NL " imageStore(g_image_2darray, ivec3(coord, 0), " << TypePrefix<T>() << "vec4" << write_value |
| << ");" NL " imageStore(g_image_2darray, ivec3(coord, 1), " << TypePrefix<T>() << "vec4" << write_value |
| << ");"; |
| break; |
| } |
| os << NL "}"; |
| return os.str(); |
| } |
| |
| template <typename T> |
| std::string GenC(const T& write_value) |
| { |
| std::ostringstream os; |
| os << NL "#define KSIZE 11" NL "layout (local_size_x = KSIZE, local_size_y = KSIZE) in;" NL "uniform " |
| << TypePrefix<T>() << "sampler2D g_sampler_2d;" NL "uniform " << TypePrefix<T>() |
| << "sampler3D g_sampler_3d;" NL "uniform " << TypePrefix<T>() << "samplerCube g_sampler_cube;" NL "uniform " |
| << TypePrefix<T>() |
| << "sampler2DArray g_sampler_2darray;" NL "layout(std430, binding = 0) buffer OutputBuffer2D {" NL " " |
| << TypePrefix<T>() << "vec4 data[KSIZE*KSIZE];" NL "} g_buff_2d;" NL |
| "layout(std430, binding = 1) buffer OutputBuffer3D {" NL " " |
| << TypePrefix<T>() << "vec4 data[KSIZE*KSIZE*2];" NL "} g_buff_3d;" NL |
| "layout(std430, binding = 2) buffer OutputBufferCube {" NL " " |
| << TypePrefix<T>() << "vec4 data[KSIZE*KSIZE*6];" NL "} g_buff_cube;" NL |
| "layout(std430, binding = 3) buffer OutputBuffer2DArray {" NL " " |
| << TypePrefix<T>() |
| << "vec4 data[KSIZE*KSIZE*2];" NL "} g_buff_2darray;" NL "void main() {" NL |
| " int cubemap_i = 2 * int(gl_LocalInvocationID.x) - KSIZE + 1;" NL |
| " int cubemap_j = 2 * int(gl_LocalInvocationID.y) - KSIZE + 1;" NL |
| " uint layer = uint(KSIZE * KSIZE);" NL |
| " g_buff_2d.data[gl_LocalInvocationIndex] = texelFetch(g_sampler_2d, ivec2(gl_LocalInvocationID), 0);" NL |
| " g_buff_3d.data[gl_LocalInvocationIndex] = texelFetch(g_sampler_3d, ivec3(gl_LocalInvocationID.xy, 0), " |
| "0);" NL " g_buff_3d.data[gl_LocalInvocationIndex + layer] = texelFetch(g_sampler_3d, " |
| "ivec3(gl_LocalInvocationID.xy, 1), 0);" NL " g_buff_2darray.data[gl_LocalInvocationIndex] = " |
| "texelFetch(g_sampler_2darray, " |
| "ivec3(gl_LocalInvocationID.xy, 0), 0);" NL |
| " g_buff_2darray.data[gl_LocalInvocationIndex + layer] = texelFetch(g_sampler_2darray, " |
| "ivec3(gl_LocalInvocationID.xy, 1), 0);" NL " g_buff_cube.data[gl_LocalInvocationIndex] = " |
| "texture(g_sampler_cube, vec3(KSIZE,cubemap_i,cubemap_j));" NL |
| " g_buff_cube.data[gl_LocalInvocationIndex + layer] = texture(g_sampler_cube, " |
| "vec3(KSIZE,cubemap_i,cubemap_j));" NL " g_buff_cube.data[gl_LocalInvocationIndex + 2u * layer] = " |
| "texture(g_sampler_cube, vec3(cubemap_i,KSIZE,cubemap_j));" NL |
| " g_buff_cube.data[gl_LocalInvocationIndex + 3u * layer] = texture(g_sampler_cube, " |
| "vec3(cubemap_i,KSIZE,cubemap_j));" NL " g_buff_cube.data[gl_LocalInvocationIndex + 4u * layer] = " |
| "texture(g_sampler_cube, vec3(cubemap_i,cubemap_j,KSIZE));" NL |
| " g_buff_cube.data[gl_LocalInvocationIndex + 5u * layer] = texture(g_sampler_cube, " |
| "vec3(cubemap_i,cubemap_j,KSIZE));" NL " //g_buff_2d.data[gl_LocalInvocationIndex] = " |
| << write_value << ";" NL "}"; |
| return os.str(); |
| } |
| }; |
| //----------------------------------------------------------------------------- |
| // 1.3.2.1 BasicAllTargetsLoad |
| //----------------------------------------------------------------------------- |
| class BasicAllTargetsLoadFS : public ShaderImageLoadStoreBase |
| { |
| GLuint m_vao; |
| GLuint m_vbo; |
| |
| virtual long Setup() |
| { |
| m_vao = 0; |
| m_vbo = 0; |
| return NO_ERROR; |
| } |
| |
| virtual long Run() |
| { |
| if (!IsVSFSAvailable(0, 4) || !IsSSBInVSFSAvailable(4)) |
| return NOT_SUPPORTED; |
| CreateFullViewportQuad(&m_vao, &m_vbo, NULL); |
| |
| if (!Read(T2D, GL_RGBA32F, vec4(-1.0f, 10.0f, -200.0f, 3000.0f), vec4(-1.0f, 10.0f, -200.0f, 3000.0f), GL_RGBA, |
| GL_FLOAT)) |
| return ERROR; |
| if (!Read(T2D, GL_RGBA32I, ivec4(-1, 10, -200, 3000), ivec4(-1, 10, -200, 3000), GL_RGBA_INTEGER, GL_INT)) |
| return ERROR; |
| if (!Read(T2D, GL_RGBA32UI, uvec4(1, 10, 200, 3000), uvec4(1, 10, 200, 3000), GL_RGBA_INTEGER, GL_UNSIGNED_INT)) |
| return ERROR; |
| if (!Read(T3D, GL_RGBA32F, vec4(-1.0f, 10.0f, -200.0f, 3000.0f), vec4(-1.0f, 10.0f, -200.0f, 3000.0f), GL_RGBA, |
| GL_FLOAT)) |
| return ERROR; |
| if (!Read(T3D, GL_RGBA32I, ivec4(-1, 10, -200, 3000), ivec4(-1, 10, -200, 3000), GL_RGBA_INTEGER, GL_INT)) |
| return ERROR; |
| if (!Read(T3D, GL_RGBA32UI, uvec4(1, 10, 200, 3000), uvec4(1, 10, 200, 3000), GL_RGBA_INTEGER, GL_UNSIGNED_INT)) |
| return ERROR; |
| if (!Read(TCM, GL_RGBA32F, vec4(-1.0f, 10.0f, -200.0f, 3000.0f), vec4(-1.0f, 10.0f, -200.0f, 3000.0f), GL_RGBA, |
| GL_FLOAT)) |
| return ERROR; |
| if (!Read(TCM, GL_RGBA32I, ivec4(-1, 10, -200, 3000), ivec4(-1, 10, -200, 3000), GL_RGBA_INTEGER, GL_INT)) |
| return ERROR; |
| if (!Read(TCM, GL_RGBA32UI, uvec4(1, 10, 200, 3000), uvec4(1, 10, 200, 3000), GL_RGBA_INTEGER, GL_UNSIGNED_INT)) |
| return ERROR; |
| if (!Read(T2DA, GL_RGBA32F, vec4(-1.0f, 10.0f, -200.0f, 3000.0f), vec4(-1.0f, 10.0f, -200.0f, 3000.0f), GL_RGBA, |
| GL_FLOAT)) |
| return ERROR; |
| if (!Read(T2DA, GL_RGBA32I, ivec4(-1, 10, -200, 3000), ivec4(-1, 10, -200, 3000), GL_RGBA_INTEGER, GL_INT)) |
| return ERROR; |
| if (!Read(T2DA, GL_RGBA32UI, uvec4(1, 10, 200, 3000), uvec4(1, 10, 200, 3000), GL_RGBA_INTEGER, |
| GL_UNSIGNED_INT)) |
| return ERROR; |
| |
| return NO_ERROR; |
| } |
| |
| virtual long Cleanup() |
| { |
| glViewport(0, 0, getWindowWidth(), getWindowHeight()); |
| glDeleteVertexArrays(1, &m_vao); |
| glDeleteBuffers(1, &m_vbo); |
| return NO_ERROR; |
| } |
| |
| template <typename T> |
| bool Read(int target, GLenum internalformat, const T& value, const T& expected_value, GLenum format, GLenum type) |
| { |
| const char* src_vs = |
| NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL " gl_Position = i_position;" NL "}"; |
| const GLuint program = BuildProgram(src_vs, GenFS(target, internalformat, expected_value).c_str()); |
| GLuint textures[8]; |
| glGenTextures(8, textures); |
| |
| const int kSize = 11; |
| std::vector<T> data(kSize * kSize * 2, value); |
| |
| glBindTexture(GL_TEXTURE_2D, textures[1]); |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
| glTexStorage2D(GL_TEXTURE_2D, 1, internalformat, kSize, kSize); |
| glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, format, type, &data[0]); |
| glBindTexture(GL_TEXTURE_2D, 0); |
| |
| glBindTexture(GL_TEXTURE_3D, textures[2]); |
| glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
| glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
| glTexStorage3D(GL_TEXTURE_3D, 1, internalformat, kSize, kSize, 2); |
| glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, kSize, kSize, 2, format, type, &data[0]); |
| glBindTexture(GL_TEXTURE_3D, 0); |
| |
| glBindTexture(GL_TEXTURE_CUBE_MAP, textures[4]); |
| glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
| glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
| glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, internalformat, kSize, kSize); |
| glTexSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, 0, 0, kSize, kSize, format, type, &data[0]); |
| glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, 0, 0, kSize, kSize, format, type, &data[0]); |
| glTexSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, 0, 0, kSize, kSize, format, type, &data[0]); |
| glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, 0, 0, kSize, kSize, format, type, &data[0]); |
| glTexSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, 0, 0, kSize, kSize, format, type, &data[0]); |
| glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, 0, 0, kSize, kSize, format, type, &data[0]); |
| glBindTexture(GL_TEXTURE_CUBE_MAP, 0); |
| |
| glBindTexture(GL_TEXTURE_2D_ARRAY, textures[7]); |
| glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
| glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
| glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, internalformat, kSize, kSize, 2); |
| glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, kSize, kSize, 2, format, type, &data[0]); |
| glBindTexture(GL_TEXTURE_2D_ARRAY, 0); |
| |
| glBindImageTexture(2, textures[1], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat); // 2D |
| glBindImageTexture(0, textures[2], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat); // 3D |
| glBindImageTexture(3, textures[4], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat); // Cube |
| glBindImageTexture(1, textures[7], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat); // 2DArray |
| |
| std::vector<T> out_data2D(kSize * kSize * 6); |
| std::vector<T> out_data3D(kSize * kSize * 6); |
| std::vector<T> out_dataCube(kSize * kSize * 6); |
| std::vector<T> out_data2DArray(kSize * kSize * 6); |
| GLuint m_buffer[4]; |
| glGenBuffers(4, m_buffer); |
| glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_buffer[0]); |
| glBufferData(GL_SHADER_STORAGE_BUFFER, 6 * kSize * kSize * 4 * 4, &out_dataCube[0], GL_STATIC_DRAW); |
| glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer[1]); |
| glBufferData(GL_SHADER_STORAGE_BUFFER, 6 * kSize * kSize * 4 * 4, &out_dataCube[0], GL_STATIC_DRAW); |
| glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_buffer[2]); |
| glBufferData(GL_SHADER_STORAGE_BUFFER, 6 * kSize * kSize * 4 * 4, &out_dataCube[0], GL_STATIC_DRAW); |
| glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_buffer[3]); |
| glBufferData(GL_SHADER_STORAGE_BUFFER, 6 * kSize * kSize * 4 * 4, &out_dataCube[0], GL_STATIC_DRAW); |
| |
| glUseProgram(program); |
| glClear(GL_COLOR_BUFFER_BIT); |
| glBindVertexArray(m_vao); |
| glViewport(0, 0, kSize, kSize); |
| glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); |
| glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT); |
| |
| bool status = true; |
| glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer[target]); |
| T* map_data = (T*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 6 * kSize * kSize * 4 * 4, GL_MAP_READ_BIT); |
| int layers = 2; |
| if (target == T2D) |
| layers = 1; |
| if (target == TCM) |
| layers = 6; |
| status = CompareValues(map_data, kSize, expected_value, internalformat, layers); |
| if (!status) |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << target << " target, " << FormatEnumToString(internalformat).c_str() |
| << " format failed." << tcu::TestLog::EndMessage; |
| glUnmapBuffer(GL_SHADER_STORAGE_BUFFER); |
| |
| glUseProgram(0); |
| glDeleteProgram(program); |
| glDeleteTextures(8, textures); |
| glDeleteBuffers(4, m_buffer); |
|