| #ifndef _ESEXTCTEXTUREBUFFEROPERATIONS_HPP |
| #define _ESEXTCTEXTUREBUFFEROPERATIONS_HPP |
| /*------------------------------------------------------------------------- |
| * 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 |
| */ /*-------------------------------------------------------------------*/ |
| |
| /*! |
| * \file esextcTextureBufferOperations.hpp |
| * \brief Texture Buffer Operations (Test 1) |
| */ /*-------------------------------------------------------------------*/ |
| |
| #include "../esextcTestCaseBase.hpp" |
| |
| namespace glcts |
| { |
| |
| /** Implementation of (Test 1) from CTS_EXT_texture_buffer. Description follows |
| * |
| * Check whether texture data for the texture buffer can be specified in a number |
| * of different ways: |
| * |
| * 1. via buffer object loads |
| * 2. via direct CPU writes |
| * 3. via framebuffer readbacks to pixel buffer objects |
| * 4. via transform feedback |
| * 5. via image store |
| * 6. via ssbo writes |
| * |
| * Category: API, Functional Test. |
| * |
| * The test should create a texture object and bind it to GL_TEXTURE_BUFFER_EXT |
| * texture target at texture unit 0. It should also create buffer object |
| * and bind it to TEXTURE_BUFFER_EXT target. Call glBufferData with NULL data |
| * pointer to allocate storage for the buffer object. The size of the storage |
| * should be equal to value(GL_MAX_COMPUTE_WORK_GROUP_SIZE, X axis) * |
| * sizeof(GLint) * 4. |
| * |
| * The buffer object should be used as texture buffer's data store by calling |
| * |
| * TexBufferExt(TEXTURE_BUFFER_EXT, GL_RGBA32I, buffer_id ); |
| * |
| * The data for the buffer object should be specified in the following ways: |
| * |
| * --------------------------------------------------------------------------- |
| * |
| * 1. Use glBufferSubData to fill buffer object's data store. |
| * glBufferSubData should be given a pointer to data that will be copied into |
| * the data store for initialization. |
| * |
| * --------------------------------------------------------------------------- |
| * |
| * 2. Map the buffer object's data store to client's address space by using |
| * glMapBufferRange function (map the whole data store). The data store should |
| * then be filled with values up to the size of the data store. |
| * The data store should be unmapped using glUnmapBuffer function. |
| * |
| * --------------------------------------------------------------------------- |
| * |
| * 3. Create a framebuffer object and bind it to GL_DRAW_FRAMEBUFFER target. |
| * Create a 2d texture object with size |
| * value(GL_MAX_COMPUTE_WORK_GROUP_SIZE, X axis) x 1 and RGBA32I internal |
| * format. Attach the texture object to framebuffer's GL_COLOR_ATTACHMENT0 |
| * attachment. Render to texture filling it completely with some predefined |
| * integer values. |
| * |
| * Bind the framebuffer object to GL_READ_FRAMEBUFFER target. |
| * |
| * Bind the buffer object to GL_PIXEL_PACK_BUFFER target. |
| * |
| * Set the alignment requirements by calling glPixelStorei(GL_UNPACK_ALIGNMENT,1) |
| * and glPixelStorei(GL_PACK_ALIGNMENT,1). |
| * |
| * Call glReadPixels(0, 0, value(GL_MAX_COMPUTE_WORK_GROUP_SIZE, X axis), |
| * 1, GL_RGBA, GL_INT, 0). |
| * |
| * Bind the buffer object once again to TEXTURE_BUFFER_EXT target. |
| * |
| * --------------------------------------------------------------------------- |
| * |
| * 4. Write a vertex shader that declares in ivec4 inPosition and |
| * out ivec4 outPosition variables and a matching fragment shader. The vertex |
| * shader should assign the value of inPosition to outPosition. The buffer object |
| * being a data source for the inPosition attribute should be filled with some |
| * integer values. Configure transform feedback to capture value of outPosition. |
| * Bind our texture buffer's buffer object as destination buffer for transform |
| * feedback operations. |
| * |
| * Execute a draw call. |
| * |
| * --------------------------------------------------------------------------- |
| * |
| * 5. Write a compute shader that defines |
| * |
| * layout(rgba32i, binding = 0) uniform highp iimageBuffer image_buffer; |
| * |
| * The work group size should be equal to |
| * value(GL_MAX_COMPUTE_WORK_GROUP_SIZE, X axis) x 1 x 1. |
| * |
| * Bind the texture buffer to image unit 0. |
| * |
| * In the compute shader execute: |
| * |
| * imageStore(image_buffer, gl_LocalInvocationID.x, ivec4(gl_LocalInvocationID.x) ); |
| * |
| * Call: |
| * |
| * glDispatchCompute(1, 1, 1); |
| * glMemoryBarrier(TEXTURE_FETCH_BARRIER_BIT); |
| * |
| * --------------------------------------------------------------------------- |
| * |
| * 6. Write a compute shader that defines |
| * |
| * buffer ComputeSSBO |
| * { |
| * ivec4 value[]; |
| * |
| * } computeSSBO; |
| * |
| * Work group size should be equal to |
| * value(GL_MAX_COMPUTE_WORK_GROUP_SIZE, X axis) x 1 x 1. |
| * |
| * Bind the buffer object to GL_SHADER_STORAGE_BUFFER target. |
| * |
| * In the compute shader execute: |
| * |
| * computeSSBO.value[gl_LocalInvocationID.x] = vec4(gl_LocalInvocationID.x); |
| * |
| * Call: |
| * |
| * glDispatchCompute(1, 1, 1); |
| * glMemoryBarrier(TEXTURE_FETCH_BARRIER_BIT); |
| * |
| * Bind the buffer object once again to TEXTURE_BUFFER_EXT target. |
| * |
| * --------------------------------------------------------------------------- |
| * |
| * The test checks whether data for the texture buffer has been correctly |
| * specified in the above 6 different ways and if it can be accessed via imageLoad |
| * and texelFetch. In the first phase we try to access the data via imageLoad in |
| * a compute shader and in the second phase we try to access the same data |
| * via texelFetch in a vertex shader. |
| * |
| * For the first phase write a compute shader that defines |
| * |
| * layout(rgba32i, binding = 0) uniform highp iimageBuffer image_buffer; |
| * |
| * Bind the texture buffer to image unit 0. |
| * |
| * Work group size should be equal to |
| * value(GL_MAX_COMPUTE_WORK_GROUP_SIZE, X axis) x 1 x 1. |
| * |
| * The shader should also define a shader storage buffer object |
| * |
| * buffer ComputeSSBO |
| * { |
| * ivec4 value[]; |
| * |
| * } computeSSBO; |
| * |
| * Initialize a buffer object to be assigned as ssbo data store. The size of |
| * this buffer object's data store should be equal to the size of |
| * the data store of the buffer object associated with texture buffer. |
| * |
| * In the compute shader execute: |
| * |
| * int index = int(gl_LocalInvocationID.x); |
| * |
| * computeSSBO.value[index] = imageLoad( image_buffer, index); |
| * |
| * Call: |
| * |
| * glDispatchCompute(1, 1, 1); |
| * glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT); |
| * |
| * For each case compare the contents of the data store of ssbo's buffer object |
| * with the values that this case should have written to the data store of the |
| * texture buffer. This phase of the test passes if for each case we get equality. |
| * |
| * For the second phase of the test write a vertex shader that defines |
| * |
| * in vec4 vs_position; |
| * in float vs_index; |
| * out float fs_index; |
| * |
| * The shader should execute the following operations: |
| * |
| * gl_Position = vs_position; |
| * fs_index = vs_index; |
| * |
| * Configure buffer object as data source for the vs_position attribute. |
| * The buffer object should be filled with data: |
| * (-1,-1,0,1), (1,-1,0,1), (-1,1,0,1), (1,1,0,1). |
| * |
| * Configure buffer object as data source for the vs_index attribute. |
| * The buffer object should be filled with data: |
| * 0.0f , 0.0f , value(GL_MAX_COMPUTE_WORK_GROUP_SIZE, X axis), |
| * value(GL_MAX_COMPUTE_WORK_GROUP_SIZE, X axis). |
| * |
| * Write a fragment shader that defines; |
| * |
| * in float fs_index; |
| * |
| * uniform highp isamplerBuffer sampler_buffer; |
| * |
| * layout(location = 0) out ivec4 color; |
| * |
| * The shader should execute the following operations: |
| * |
| * color = texelFetch( sampler_buffer, int(fs_index) ); |
| * |
| * Create a program from the above vertex shader and fragment shader and use it. |
| * |
| * Bind the sampler_buffer location to texture unit 0. |
| * |
| * The test should set up a FBO. A 2D texture of |
| * value(GL_MAX_COMPUTE_WORK_GROUP_SIZE, X axis) x 1 resolution using |
| * GL_RGBA32I internal format and GL_NEAREST magnification and |
| * minification filter should be attached to its color attachment 0. |
| * |
| * Execute a draw call glDrawArrays(GL_TRIANGLE_STRIP, 0, 4). |
| * |
| * Use glReadPixels to read the texel data from the texture attached to color |
| * attachment 0. |
| * |
| * For each case compare the contents of retrieved texel data with the values |
| * that this case should have written to the data store of the texture buffer. |
| * This phase of the test passes if for each case we get equality. |
| */ |
| |
| /* Base Class */ |
| class TextureBufferOperations : public TestCaseBase |
| { |
| public: |
| /* Public methods */ |
| TextureBufferOperations(Context& context, const ExtParameters& extParams, const char* name, |
| const char* description); |
| |
| virtual ~TextureBufferOperations() |
| { |
| } |
| |
| virtual void deinit(void); |
| virtual IterateResult iterate(void); |
| |
| protected: |
| /* Protected methods */ |
| void checkFramebufferStatus(glw::GLenum framebuffer); |
| virtual void initTest(void); |
| virtual void initializeBufferObjectData(void) = 0; |
| virtual void fillBufferWithData(glw::GLint* buffer, glw::GLuint bufferLength); |
| |
| /* Protected static constants */ |
| static const glw::GLuint m_n_vector_components; |
| |
| /* Protected variables */ |
| glw::GLint m_n_vectors_in_buffer_texture; |
| |
| glw::GLuint m_tb_bo_id; |
| glw::GLuint m_texbuff_id; |
| |
| private: |
| std::string getComputeShaderCode(void) const; |
| std::string getFragmentShaderCode(void) const; |
| std::string getVertexShaderCode(void) const; |
| |
| void initFirstPhase(void); |
| void initSecondPhase(void); |
| void iterateFirstPhase(glw::GLint* result, glw::GLuint size); |
| void iterateSecondPhase(glw::GLint* result); |
| void deinitFirstPhase(void); |
| void deinitSecondPhase(void); |
| |
| glw::GLboolean verifyResults(glw::GLint* reference, glw::GLint* result, glw::GLuint size, const char* message); |
| |
| /* Private variables */ |
| glw::GLuint m_cs_id; |
| glw::GLuint m_po_cs_id; |
| glw::GLuint m_ssbo_bo_id; |
| |
| glw::GLuint m_fbo_id; |
| glw::GLuint m_fs_id; |
| glw::GLuint m_po_vs_fs_id; |
| glw::GLuint m_to_id; |
| glw::GLuint m_vao_id; |
| glw::GLuint m_vbo_id; |
| glw::GLuint m_vbo_indicies_id; |
| glw::GLuint m_vs_id; |
| glw::GLint m_vertex_location; |
| glw::GLint m_index_location; |
| }; |
| |
| /* Test Case 1 - buffer object loads */ |
| class TextureBufferOperationsViaBufferObjectLoad : public TextureBufferOperations |
| { |
| public: |
| /* Public methods */ |
| TextureBufferOperationsViaBufferObjectLoad(Context& context, const ExtParameters& extParams, const char* name, |
| const char* description); |
| |
| virtual ~TextureBufferOperationsViaBufferObjectLoad() |
| { |
| } |
| |
| protected: |
| /* Protected methods */ |
| virtual void initializeBufferObjectData(void); |
| }; |
| |
| /* Test Case 2 - direct CPU writes */ |
| class TextureBufferOperationsViaCPUWrites : public TextureBufferOperations |
| { |
| public: |
| /* Public methods */ |
| TextureBufferOperationsViaCPUWrites(Context& context, const ExtParameters& extParams, const char* name, |
| const char* description); |
| |
| virtual ~TextureBufferOperationsViaCPUWrites() |
| { |
| } |
| |
| protected: |
| /* Protected methods */ |
| virtual void initializeBufferObjectData(void); |
| }; |
| |
| /* Test Case 3 - framebuffer readbacks to pixel buffer objects */ |
| class TextureBufferOperationsViaFrambufferReadBack : public TextureBufferOperations |
| { |
| public: |
| /* Public methods */ |
| TextureBufferOperationsViaFrambufferReadBack(Context& context, const ExtParameters& extParams, const char* name, |
| const char* description); |
| |
| virtual ~TextureBufferOperationsViaFrambufferReadBack() |
| { |
| } |
| |
| virtual void deinit(void); |
| |
| private: |
| /* Private methods */ |
| virtual void initializeBufferObjectData(void); |
| virtual void fillBufferWithData(glw::GLint* buffer, glw::GLuint bufferLength); |
| |
| std::string getFBFragmentShaderCode() const; |
| std::string getFBVertexShaderCode() const; |
| |
| glw::GLuint m_fb_fbo_id; |
| glw::GLuint m_fb_fs_id; |
| glw::GLuint m_fb_po_id; |
| glw::GLuint m_fb_to_id; |
| glw::GLuint m_fb_vao_id; |
| glw::GLuint m_fb_vbo_id; |
| glw::GLuint m_fb_vs_id; |
| glw::GLint m_position_location; |
| }; |
| |
| /* Test Case 4 - transform feedback */ |
| class TextureBufferOperationsViaTransformFeedback : public TextureBufferOperations |
| { |
| public: |
| /* Public methods */ |
| TextureBufferOperationsViaTransformFeedback(Context& context, const ExtParameters& extParams, const char* name, |
| const char* description); |
| |
| virtual ~TextureBufferOperationsViaTransformFeedback() |
| { |
| } |
| |
| virtual void deinit(void); |
| |
| private: |
| /* Private methods */ |
| virtual void initializeBufferObjectData(void); |
| |
| std::string getTFVertexShaderCode() const; |
| std::string getTFFragmentShaderCode() const; |
| |
| /* Private variables */ |
| glw::GLuint m_tf_fs_id; |
| glw::GLuint m_tf_po_id; |
| glw::GLuint m_tf_vao_id; |
| glw::GLuint m_tf_vbo_id; |
| glw::GLuint m_tf_vs_id; |
| glw::GLint m_position_location; |
| }; |
| |
| /* Test Case 5 - image store */ |
| class TextureBufferOperationsViaImageStore : public TextureBufferOperations |
| { |
| public: |
| /* Public methods */ |
| TextureBufferOperationsViaImageStore(Context& context, const ExtParameters& extParams, const char* name, |
| const char* description); |
| |
| virtual ~TextureBufferOperationsViaImageStore() |
| { |
| } |
| |
| virtual void deinit(void); |
| |
| private: |
| /* Private methods */ |
| virtual void initializeBufferObjectData(void); |
| virtual void fillBufferWithData(glw::GLint* buffer, glw::GLuint bufferLength); |
| |
| std::string getISComputeShaderCode() const; |
| |
| /* Private Variables */ |
| glw::GLuint m_is_cs_id; |
| glw::GLuint m_is_po_id; |
| |
| /* Private static constants */ |
| static const glw::GLuint m_image_unit; |
| }; |
| |
| /* Test Case 6 - ssbo writes */ |
| class TextureBufferOperationsViaSSBOWrites : public TextureBufferOperations |
| { |
| public: |
| /* Public methods */ |
| TextureBufferOperationsViaSSBOWrites(Context& context, const ExtParameters& extParams, const char* name, |
| const char* description); |
| |
| virtual ~TextureBufferOperationsViaSSBOWrites() |
| { |
| } |
| |
| virtual void deinit(void); |
| |
| private: |
| /* Private methods */ |
| virtual void initializeBufferObjectData(void); |
| virtual void fillBufferWithData(glw::GLint* buffer, glw::GLuint bufferLength); |
| |
| std::string getSSBOComputeShaderCode() const; |
| |
| /* Private variables */ |
| glw::GLuint m_ssbo_cs_id; |
| glw::GLuint m_ssbo_po_id; |
| }; |
| |
| } // namespace glcts |
| |
| #endif // _ESEXTCTEXTUREBUFFEROPERATIONS_HPP |