Browse Source

Implemented ARB_shader_image_load_store.

pull/132/head
Vladimír Vondruš 10 years ago
parent
commit
d9b25c6057
  1. 2
      doc/opengl-mapping.dox
  2. 4
      doc/opengl-support.dox
  3. 13
      src/Magnum/AbstractShaderProgram.h
  4. 56
      src/Magnum/AbstractTexture.cpp
  5. 92
      src/Magnum/AbstractTexture.h
  6. 22
      src/Magnum/BufferTexture.h
  7. 1
      src/Magnum/CMakeLists.txt
  8. 49
      src/Magnum/CubeMapTexture.h
  9. 47
      src/Magnum/CubeMapTextureArray.h
  10. 315
      src/Magnum/ImageFormat.h
  11. 17
      src/Magnum/Implementation/TextureState.cpp
  12. 4
      src/Magnum/Implementation/TextureState.h
  13. 5
      src/Magnum/Magnum.h
  14. 76
      src/Magnum/MultisampleTexture.h
  15. 19
      src/Magnum/RectangleTexture.h
  16. 42
      src/Magnum/Test/BufferTextureGLTest.cpp
  17. 40
      src/Magnum/Test/CubeMapTextureArrayGLTest.cpp
  18. 44
      src/Magnum/Test/CubeMapTextureGLTest.cpp
  19. 78
      src/Magnum/Test/MultisampleTextureGLTest.cpp
  20. 28
      src/Magnum/Test/RectangleTextureGLTest.cpp
  21. 78
      src/Magnum/Test/TextureArrayGLTest.cpp
  22. 109
      src/Magnum/Test/TextureGLTest.cpp
  23. 84
      src/Magnum/Texture.h
  24. 49
      src/Magnum/TextureArray.h

2
doc/opengl-mapping.dox

@ -60,7 +60,7 @@ OpenGL function | Matching API
@fn_gl{BindFragDataLocation} | @ref AbstractShaderProgram::bindFragmentDataLocation()
@fn_gl{BindFragDataLocationIndexed} | @ref AbstractShaderProgram::bindFragmentDataLocationIndexed()
@fn_gl{BindFramebuffer} | @ref Framebuffer::bind()
@fn_gl{BindImageTexture}, \n @fn_gl{BindImageTextures} | |
@fn_gl{BindImageTexture}, \n @fn_gl{BindImageTextures} | @ref AbstractTexture::unbindImage(), \n @ref AbstractTexture::unbindImages(), \n @ref AbstractTexture::bindImages(), \n @ref Texture::bindImage(), \n @ref Texture::bindImageLayered(), \n @ref TextureArray::bindImage(), \n @ref TextureArray::bindImageLayered(), \n @ref CubeMapTexture::bindImage(), \n @ref CubeMapTexture::bindImageLayered(), \n @ref CubeMapTextureArray::bindImage(), \n @ref CubeMapTextureArray::bindImageLayered(), \n @ref MultisampleTexture::bindImage(), \n @ref MultisampleTexture::bindImageLayered(), \n @ref RectangleTexture::bindImage(), \n @ref BufferTexture::bindImage()
@fn_gl{BindProgramPipeline} | |
@fn_gl{BindRenderbuffer} | not needed, handled internally in @ref Renderbuffer
@fn_gl{BindSampler}, \n @fn_gl{BindSamplers} | |

4
doc/opengl-support.dox

@ -161,7 +161,7 @@ GLSL 4.20 | done
@extension{ARB,internalformat_query} | |
@extension{ARB,map_buffer_alignment} | done
@extension{ARB,shader_atomic_counters} | done
@extension{ARB,shader_image_load_store} | |
@extension{ARB,shader_image_load_store} | done
@extension{ARB,shading_language_packing} | done (shading language only)
@extension{ARB,texture_storage} | done
@ -205,7 +205,7 @@ GLSL 4.40 | done
@extension{ARB,buffer_storage} | |
@extension{ARB,clear_texture} | |
@extension{ARB,enhanced_layouts} | done (shading language only)
@extension{ARB,multi_bind} | only texture and buffer binding
@extension{ARB,multi_bind} | missing sampler and vertex buffer binding
@extension{ARB,query_buffer_object} | |
@extension{ARB,texture_mirror_clamp_to_edge} | done
@extension{ARB,texture_stencil8} | done

13
src/Magnum/AbstractShaderProgram.h

@ -99,9 +99,10 @@ MyShader& setNormalMatrix(const Matrix3x3& matrix) {
return *this;
}
@endcode
- **Texture setting functions** in which you bind the textures
to particular texture units using @ref Texture::bind() "*Texture::bind()"
and equivalents, for example:
- **Texture and texture image setting functions** in which you bind the
textures/images to particular texture/image units using
@ref Texture::bind() "*Texture::bind()" /
@ref Texture::bindImage() "*Texture::bindImage()" and similar, for example:
@code
MyShader& setDiffuseTexture(Texture2D& texture) {
texture.bind(0);
@ -311,9 +312,9 @@ layout(std430, binding = 1) buffer normals {
@requires_gles Shader storage is not available in WebGL.
@anchor AbstractShaderProgram-texture-units
### Specifying texture binding units
### Specifying texture and image binding units
The preferred workflow is to specify texture binding unit directly in the
The preferred workflow is to specify texture/image binding unit directly in the
shader code, e.g.:
@code
// GLSL 4.20, GLSL ES 3.10 or
@ -335,7 +336,7 @@ setUniform(uniformLocation("diffuseTexture"), 0);
setUniform(uniformLocation("specularTexture"), 1);
@endcode
@see @ref Shader::maxTextureImageUnits()
@see @ref Shader::maxTextureImageUnits(), @ref maxImageUnits()
@requires_gl42 Extension @extension{ARB,shading_language_420pack} for explicit
texture binding unit instead of using
@ref setUniform(Int, const T&) "setUniform(Int, Int)".

56
src/Magnum/AbstractTexture.cpp

@ -269,6 +269,62 @@ AbstractTexture& AbstractTexture::setLabelInternal(const Containers::ArrayView<c
}
#endif
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
void AbstractTexture::unbindImage(const Int imageUnit) {
Implementation::TextureState& textureState = *Context::current().state().texture;
/* If already unbound in given image unit, nothing to do */
if(std::get<0>(textureState.imageBindings[imageUnit]) == 0) return;
/* Update state tracker, bind the texture to the unit */
std::get<0>(textureState.imageBindings[imageUnit]) = 0;
glBindImageTexture(imageUnit, 0, 0, false, 0, GL_READ_ONLY, GL_R8);
}
#ifndef MAGNUM_TARGET_GLES
/** @todoc const Containers::ArrayView makes Doxygen grumpy */
void AbstractTexture::bindImagesInternal(const Int firstImageUnit, Containers::ArrayView<AbstractTexture* const> textures) {
Implementation::TextureState& textureState = *Context::current().state().texture;
/* Create array of IDs and also update bindings in state tracker */
Containers::Array<GLuint> ids{textures ? textures.size() : 0};
bool different = false;
for(std::size_t i = 0; i != textures.size(); ++i) {
const std::tuple<GLuint, GLint, GLboolean, GLint, GLenum> state = textures && textures[i] ?
std::tuple<GLuint, GLint, GLboolean, GLint, GLenum>(textures[i]->_id, 0, true, 0, GL_READ_WRITE) :
std::tuple<GLuint, GLint, GLboolean, GLint, GLenum>(0, 0, false, 0, GL_READ_ONLY);
if(textures) {
if(textures[i]) {
textures[i]->createIfNotAlready();
}
ids[i] = std::get<0>(state);
}
if(textureState.imageBindings[firstImageUnit + i] != state) {
different = true;
textureState.imageBindings[firstImageUnit + i] = state;
}
}
/* Avoid doing the binding if there is nothing different */
if(different) glBindImageTextures(firstImageUnit, textures.size(), ids);
}
#endif
void AbstractTexture::bindImageInternal(const Int imageUnit, const Int level, const bool layered, const Int layer, const ImageAccess access, const ImageFormat format) {
Implementation::TextureState& textureState = *Context::current().state().texture;
const std::tuple<GLuint, GLint, GLboolean, GLint, GLenum> state{_id, level, layered, layer, GLenum(access)};
/* If already bound in given texture unit, nothing to do */
if(textureState.imageBindings[imageUnit] == state) return;
/* Update state tracker, bind the texture to the unit */
textureState.imageBindings[imageUnit] = state;
glBindImageTexture(imageUnit, _id, level, layered, layer, GLenum(access), GLenum(format));
}
#endif
void AbstractTexture::bind(Int textureUnit) {
Implementation::TextureState& textureState = *Context::current().state().texture;

92
src/Magnum/AbstractTexture.h

@ -69,13 +69,13 @@ documentation for details.
@anchor AbstractTexture-performance-optimization
## Performance optimizations and security
The engine tracks currently bound textures in all available texture units to
avoid unnecessary calls to @fn_gl{ActiveTexture} and @fn_gl{BindTexture}.
Texture configuration functions use dedicated highest available texture unit
to not affect active bindings in user units. Texture limits and
implementation-defined values (such as @ref maxColorSamples()) are cached, so
repeated queries don't result in repeated @fn_gl{Get} calls. See also
@ref Context::resetState() and @ref Context::State::Textures.
The engine tracks currently bound textures and images in all available texture
units to avoid unnecessary calls to @fn_gl{ActiveTexture}, @fn_gl{BindTexture}
and @fn_gl{BindImageTexture}. Texture configuration functions use dedicated
highest available texture unit to not affect active bindings in user units.
Texture limits and implementation-defined values (such as @ref maxColorSamples())
are cached, so repeated queries don't result in repeated @fn_gl{Get} calls. See
also @ref Context::resetState() and @ref Context::State::Textures.
If @extension{ARB,direct_state_access} (part of OpenGL 4.5) is available,
@ref bind(Int) and @ref unbind(Int) use @fn_gl{BindTextureUnit}. Otherwise, if
@ -209,13 +209,14 @@ class MAGNUM_EXPORT AbstractTexture: public AbstractObject {
/**
* @brief Unbind textures in given range of texture units
*
* Unbinds all texture in the range @f$ [ firstTextureUnit ; firstTextureUnit + count ) @f$.
* Unbinds all textures in the range @f$ [ firstTextureUnit ; firstTextureUnit + count ) @f$.
* If @extension{ARB,multi_bind} (part of OpenGL 4.4) is not available,
* the feature is emulated with sequence of @ref unbind(Int) calls.
* @note This function is meant to be used only internally from
* @ref AbstractShaderProgram subclasses. See its documentation
* for more information.
* @see @ref Shader::maxCombinedTextureImageUnits(), @fn_gl{BindTextures}
* @see @ref bind(), @ref Shader::maxCombinedTextureImageUnits(),
* @fn_gl{BindTextures}
*/
static void unbind(Int firstTextureUnit, std::size_t count);
@ -234,6 +235,71 @@ class MAGNUM_EXPORT AbstractTexture: public AbstractObject {
*/
static void bind(Int firstTextureUnit, std::initializer_list<AbstractTexture*> textures);
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
/**
* @brief Unbind any image from given image unit
*
* @note This function is meant to be used only internally from
* @ref AbstractShaderProgram subclasses. See its documentation
* for more information.
* @see @ref Texture::bindImage() "*Texture::bindImage()",
* @ref Texture::bindImageLayered() "*Texture::bindImageLayered()",
* @ref unbindImages(), @ref bindImages(),
* @ref AbstractShaderProgram::maxImageUnits(),
* @fn_gl{BindImageTexture}
* @requires_gl42 Extension @extension{ARB,shader_image_load_store}
* @requires_gles31 Shader image load/store is not available in OpenGL
* ES 3.0 and older.
* @requires_gles Shader image load/store is not available in WebGL.
*/
static void unbindImage(Int imageUnit);
#endif
#ifndef MAGNUM_TARGET_GLES
/**
* @brief Unbind images in given range of image units
*
* Unbinds all texture in the range @f$ [ firstImageUnit ; firstImageUnit + count ) @f$.
* @note This function is meant to be used only internally from
* @ref AbstractShaderProgram subclasses. See its documentation
* for more information.
* @see @ref Texture::bindImage() "*Texture::bindImage()",
* @ref Texture::bindImageLayered() "*Texture::bindImageLayered()",
* @ref unbindImage(), @ref bindImages(),
* @ref AbstractShaderProgram::maxImageUnits(),
* @fn_gl{BindImageTextures}
* @requires_gl42 Extension @extension{ARB,shader_image_load_store}
* @requires_gl44 Extension @extension{ARB,multi_bind}
* @requires_gl Multi bind is not available in OpenGL ES and WebGL.
*/
static void unbindImages(Int firstImageUnit, std::size_t count) {
bindImagesInternal(firstImageUnit, {nullptr, count});
}
/**
* @brief Bind textures to given range of texture units
*
* Binds first level of given texture in the list to @p firstImageUnit,
* second to `firstTextureUnit + 1` etc. 3D, cube map and array
* textures are bound as layered targets. If any texture is `nullptr`,
* given image unit is unbound.
* @note This function is meant to be used only internally from
* @ref AbstractShaderProgram subclasses. See its documentation
* for more information.
* @see @ref Texture::bindImage() "*Texture::bindImage()",
* @ref Texture::bindImageLayered() "*Texture::bindImageLayered()",
* @ref unbindImages(), @ref unbindImage(),
* @ref AbstractShaderProgram::maxImageUnits(),
* @fn_gl{BindImageTextures}
* @requires_gl42 Extension @extension{ARB,shader_image_load_store}
* @requires_gl44 Extension @extension{ARB,multi_bind}
* @requires_gl Multi bind is not available in OpenGL ES and WebGL.
*/
static void bindImages(Int firstImageUnit, std::initializer_list<AbstractTexture*> textures) {
bindImagesInternal(firstImageUnit, {textures.begin(), textures.size()});
}
#endif
/** @brief Copying is not allowed */
AbstractTexture(const AbstractTexture&) = delete;
@ -342,6 +408,10 @@ class MAGNUM_EXPORT AbstractTexture: public AbstractObject {
static Int compressedBlockDataSize(GLenum target, TextureFormat format);
#endif
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
static void bindImagesInternal(Int firstImageUnit, Containers::ArrayView<AbstractTexture* const> textures);
#endif
explicit AbstractTexture(GLenum target);
explicit AbstractTexture(NoCreateT, GLenum target) noexcept: _target{target}, _id{0}, _flags{ObjectFlag::DeleteOnDestruction} {}
explicit AbstractTexture(GLuint id, GLenum target, ObjectFlags flags) noexcept: _target{target}, _id{id}, _flags{flags} {}
@ -352,6 +422,10 @@ class MAGNUM_EXPORT AbstractTexture: public AbstractObject {
void MAGNUM_LOCAL createIfNotAlready();
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
void bindImageInternal(Int imageUnit, Int level, bool layered, Int layer, ImageAccess access, ImageFormat format);
#endif
/* Unlike bind() this also sets the texture binding unit as active */
void MAGNUM_LOCAL bindInternal();

22
src/Magnum/BufferTexture.h

@ -157,6 +157,28 @@ class MAGNUM_EXPORT BufferTexture: public AbstractTexture {
AbstractTexture{NoCreate, GL_TEXTURE_BUFFER_EXT} {}
#endif
/**
* @brief Bind texture to given image unit
* @param imageUnit Image unit
* @param access Image access
* @param format Image format
*
* @note This function is meant to be used only internally from
* @ref AbstractShaderProgram subclasses. See its documentation
* for more information.
* @see @ref bindImages(Int, std::initializer_list<AbstractTexture*>),
* @ref unbindImage(), @ref unbindImages(),
* @ref AbstractShaderProgram::maxImageUnits(),
* @fn_gl{BindImageTexture}
* @requires_gl42 Extension @extension{ARB,shader_image_load_store}
* @requires_gles31 Shader image load/store is not available in OpenGL
* ES 3.0 and older.
* @requires_gles Shader image load/store is not available in WebGL.
*/
void bindImage(Int imageUnit, ImageAccess access, ImageFormat format) {
bindImageInternal(imageUnit, 0, false, 0, access, format);
}
/**
* @brief Set texture buffer
* @param internalFormat Internal format

1
src/Magnum/CMakeLists.txt

@ -187,6 +187,7 @@ if(NOT TARGET_WEBGL)
BufferTexture.h
BufferTextureFormat.h
CubeMapTextureArray.h
ImageFormat.h
MultisampleTexture.h)
endif()

49
src/Magnum/CubeMapTexture.h

@ -166,6 +166,55 @@ class MAGNUM_EXPORT CubeMapTexture: public AbstractTexture {
*/
explicit CubeMapTexture(NoCreateT) noexcept: AbstractTexture{NoCreate, GL_TEXTURE_CUBE_MAP} {}
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
/**
* @brief Bind level of given cube map texture coordinate to given image unit
* @param imageUnit Image unit
* @param level Texture level
* @param coordinate Cube map coordinate
* @param access Image access
* @param format Image format
*
* @note This function is meant to be used only internally from
* @ref AbstractShaderProgram subclasses. See its documentation
* for more information.
* @see @ref bindImages(Int, std::initializer_list<AbstractTexture*>),
* @ref bindImageLayered(), @ref unbindImage(), @ref unbindImages(),
* @ref AbstractShaderProgram::maxImageUnits(),
* @fn_gl{BindImageTexture}
* @requires_gl42 Extension @extension{ARB,shader_image_load_store}
* @requires_gles31 Shader image load/store is not available in OpenGL
* ES 3.0 and older.
* @requires_gles Shader image load/store is not available in WebGL.
*/
void bindImage(Int imageUnit, Int level, Coordinate coordinate, ImageAccess access, ImageFormat format) {
bindImageInternal(imageUnit, level, false, GLenum(coordinate) - GL_TEXTURE_CUBE_MAP_POSITIVE_X, access, format);
}
/**
* @brief Bind level of layered cube map texture to given image unit
* @param imageUnit Image unit
* @param level Texture level
* @param access Image access
* @param format Image format
*
* @note This function is meant to be used only internally from
* @ref AbstractShaderProgram subclasses. See its documentation
* for more information.
* @see @ref bindImages(Int, std::initializer_list<AbstractTexture*>),
* @ref bindImage(), @ref unbindImage(), @ref unbindImages(),
* @ref AbstractShaderProgram::maxImageUnits(),
* @fn_gl{BindImageTexture}
* @requires_gl42 Extension @extension{ARB,shader_image_load_store}
* @requires_gles31 Shader image load/store is not available in OpenGL
* ES 3.0 and older.
* @requires_gles Shader image load/store is not available in WebGL.
*/
void bindImageLayered(Int imageUnit, Int level, ImageAccess access, ImageFormat format) {
bindImageInternal(imageUnit, level, true, 0, access, format);
}
#endif
#ifndef MAGNUM_TARGET_GLES2
/**
* @copybrief Texture::setBaseLevel()

47
src/Magnum/CubeMapTextureArray.h

@ -173,6 +173,53 @@ class MAGNUM_EXPORT CubeMapTextureArray: public AbstractTexture {
AbstractTexture{NoCreate, GL_TEXTURE_CUBE_MAP_ARRAY_EXT} {}
#endif
/**
* @brief Bind level of given texture layer to given image unit
* @param imageUnit Image unit
* @param level Texture level
* @param layer Texture layer
* @param access Image access
* @param format Image format
*
* Layer is equivalent to layer * 6 + number of texture face, i.e. +X
* is `0` and so on, in order of (+X, -X, +Y, -Y, +Z, -Z).
* @note This function is meant to be used only internally from
* @ref AbstractShaderProgram subclasses. See its documentation
* for more information.
* @see @ref bindImages(Int, std::initializer_list<AbstractTexture*>),
* @ref bindImageLayered(), @ref unbindImage(), @ref unbindImages(),
* @ref AbstractShaderProgram::maxImageUnits(),
* @fn_gl{BindImageTexture}
* @requires_gl42 Extension @extension{ARB,shader_image_load_store}
* @requires_gles31 Shader image load/store is not available in OpenGL
* ES 3.0 and older.
*/
void bindImage(Int imageUnit, Int level, Int layer, ImageAccess access, ImageFormat format) {
bindImageInternal(imageUnit, level, false, layer, access, format);
}
/**
* @brief Bind level of layered texture to given image unit
* @param imageUnit Image unit
* @param level Texture level
* @param access Image access
* @param format Image format
*
* @note This function is meant to be used only internally from
* @ref AbstractShaderProgram subclasses. See its documentation
* for more information.
* @see @ref bindImages(Int, std::initializer_list<AbstractTexture*>),
* @ref bindImage(), @ref unbindImage(), @ref unbindImages(),
* @ref AbstractShaderProgram::maxImageUnits(),
* @fn_gl{BindImageTexture}
* @requires_gl42 Extension @extension{ARB,shader_image_load_store}
* @requires_gles31 Shader image load/store is not available in OpenGL
* ES 3.0 and older.
*/
void bindImageLayered(Int imageUnit, Int level, ImageAccess access, ImageFormat format) {
bindImageInternal(imageUnit, level, true, 0, access, format);
}
/**
* @copybrief Texture::setBaseLevel()
* @return Reference to self (for method chaining)

315
src/Magnum/ImageFormat.h

@ -0,0 +1,315 @@
#ifndef Magnum_ImageFormat_h
#define Magnum_ImageFormat_h
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015
Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
/** @file
* @brief Enum @ref Magnum::ImageAccess, @ref Magnum::ImageFormat
*/
#endif
#include <Magnum/OpenGL.h>
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
namespace Magnum {
/**
@brief Image access
@see @ref Texture::bindImage() "*Texture::bindImage()",
@ref Texture::bindImageLayered() "*Texture::bindImageLayered()"
@requires_gl42 Extension @extension{ARB,shader_image_load_store}
@requires_gles31 Shader image load/store is not available in OpenGL ES 3.0 and
older.
@requires_gles Shader image load/store is not available in WebGL.
*/
enum class ImageAccess: GLenum {
ReadOnly = GL_READ_ONLY,
WriteOnly = GL_WRITE_ONLY,
ReadWrite = GL_READ_WRITE
};
/**
@brief Image format
@see @ref Texture::bindImage() "*Texture::bindImage()",
@ref Texture::bindImageLayered() "*Texture::bindImageLayered()"
@requires_gl42 Extension @extension{ARB,shader_image_load_store}
@requires_gles31 Shader image load/store is not available in OpenGL ES 3.0 and
older.
@requires_gles Shader image load/store is not available in WebGL.
*/
enum class ImageFormat: GLenum {
#ifndef MAGNUM_TARGET_GLES
/**
* Red component, normalized unsigned byte.
* @requires_gl Only four-component byte image formats are available in
* OpenGL ES.
*/
R8 = GL_R8,
/**
* Red and green component, each normalized unsigned byte.
* @requires_gl Only four-component byte image formats are available in
* OpenGL ES.
*/
RG8 = GL_RG8,
#endif
/** RGBA, each component normalized unsigned byte. */
RGBA8 = GL_RGBA8,
#ifndef MAGNUM_TARGET_GLES
/**
* Red component, normalized signed byte.
* @requires_gl Only four-component byte image formats are available in
* OpenGL ES.
*/
R8Snorm = GL_R8_SNORM,
/**
* Red and green component, each normalized signed byte.
* @requires_gl Only four-component byte image formats are available in
* OpenGL ES.
*/
RG8Snorm = GL_RG8_SNORM,
#endif
/** RGBA, each component normalized unsigned byte. */
RGBA8Snorm = GL_RGBA8_SNORM,
#ifndef MAGNUM_TARGET_GLES
/**
* Red component, normalized unsigned short.
* @requires_gl Only byte-size normalized image formats are available in
* OpenGL ES.
*/
R16 = GL_R16,
/**
* Red and green component, each normalized unsigned short.
* @requires_gl Only byte-size normalized image formats are available in
* OpenGL ES.
*/
RG16 = GL_RG16,
/**
* RGBA, each component normalized unsigned short.
* @requires_gl Only byte-size normalized image formats are available in
* OpenGL ES.
*/
RGBA16 = GL_RGBA16,
/**
* Red component, normalized signed short.
* @requires_gl Only byte-size normalized image formats are available in
* OpenGL ES.
*/
R16Snorm = GL_R16_SNORM,
/**
* Red and green component, each normalized signed short.
* @requires_gl Only byte-size normalized image formats are available in
* OpenGL ES.
*/
RG16Snorm = GL_RG16_SNORM,
/**
* RGBA, each component normalized unsigned short.
* @requires_gl Only byte-size normalized image formats are available in
* OpenGL ES.
*/
RGBA16Snorm = GL_RGBA16_SNORM,
#endif
#ifndef MAGNUM_TARGET_GLES
/**
* Red component, non-normalized unsigned byte.
* @requires_gl Only four-component byte image formats are available in
* OpenGL ES.
*/
R8UI = GL_R8UI,
/**
* Red and green component, each non-normalized unsigned byte.
* @requires_gl Only four-component byte image formats are available in
* OpenGL ES.
*/
RG8UI = GL_RG8UI,
#endif
/** RGBA, each component non-normalized unsigned byte. */
RGBA8UI = GL_RGBA8UI,
#ifndef MAGNUM_TARGET_GLES
/**
* Red component, non-normalized signed byte.
* @requires_gl Only four-component byte image formats are available in
* OpenGL ES.
*/
R8I = GL_R8I,
/**
* Red and green component, each non-normalized signed byte.
* @requires_gl Only four-component byte image formats are available in
* OpenGL ES.
*/
RG8I = GL_RG8I,
#endif
/** RGBA, each component non-normalized signed byte. */
RGBA8I = GL_RGBA8I,
#ifndef MAGNUM_TARGET_GLES
/**
* Red component, non-normalized unsigned short.
* @requires_gl Only four-component short image formats are available in
* OpenGL ES.
*/
R16UI = GL_R16UI,
/**
* Red and green component, each non-normalized unsigned short.
* @requires_gl Only four-component short image formats are available in
* OpenGL ES.
*/
RG16UI = GL_RG16UI,
#endif
/** RGBA, each component non-normalized unsigned short. */
RGBA16UI = GL_RGBA16UI,
#ifndef MAGNUM_TARGET_GLES
/**
* Red component, non-normalized signed short.
* @requires_gl Only four-component short image formats are available in
* OpenGL ES.
*/
R16I = GL_R16I,
/**
* Red and green component, each non-normalized signed short.
* @requires_gl Only four-component short image formats are available in
* OpenGL ES.
*/
RG16I = GL_RG16I,
#endif
/** RGBA, each component non-normalized signed short. */
RGBA16I = GL_RGBA16I,
/** Red component, non-normalized unsigned int. */
R32UI = GL_R32UI,
#ifndef MAGNUM_TARGET_GLES
/**
* Red and green component, each non-normalized unsigned int.
* @requires_gl Only one- or four-component int image formats are available
* in OpenGL ES.
*/
RG32UI = GL_RG32UI,
#endif
/** RGBA, each component non-normalized unsigned int. */
RGBA32UI = GL_RGBA32UI,
/** Red component, non-normalized signed int. */
R32I = GL_R32I,
#ifndef MAGNUM_TARGET_GLES
/**
* Red and green component, each non-normalized signed int.
* @requires_gl Only one- or four-component int image formats are available
* in OpenGL ES.
*/
RG32I = GL_RG32I,
#endif
/** RGBA, each component non-normalized signed int. */
RGBA32I = GL_RGBA32I,
#ifndef MAGNUM_TARGET_GLES
/**
* Red component, half float.
* @requires_gl Only four-component half float image formats are available
* in OpenGL ES.
*/
R16F = GL_R16F,
/**
* Red and green component, each half float.
* @requires_gl Only four-component half float image formats are available
* in OpenGL ES.
*/
RG16F = GL_RG16F,
#endif
/** RGBA, each component half float. */
RGBA16F = GL_RGBA16F,
/** Red component, float. */
R32F = GL_R32F,
#ifndef MAGNUM_TARGET_GLES
/**
* Red and green component, each float.
* @requires_gl Only one- or four-component float image formats are
* available in OpenGL ES.
*/
RG32F = GL_RG32F,
#endif
/** RGBA, each component float. */
RGBA32F = GL_RGBA32F,
#ifndef MAGNUM_TARGET_GLES
/**
* RGB, float, red and green component 11bit, blue 10bit.
* @requires_gl Packed image formats are not available in OpenGL ES.
*/
R11FG11FB10F = GL_R11F_G11F_B10F,
/**
* RGBA, normalized unsigned, each RGB component 10bit, alpha 2bit.
* @requires_gl Packed image formats are not available in OpenGL ES.
*/
RGB10A2 = GL_RGB10_A2,
/**
* RGBA, non-normalized unsigned, each RGB component 10bit, alpha 2bit.
* @requires_gl33 Extension @extension{ARB,texture_rgb10_a2ui}
* @requires_gl Packed image formats are not available in OpenGL ES.
*/
RGB10A2UI = GL_RGB10_A2UI,
#endif
};
}
#else
#error this header is not available in OpenGL ES 2.0 and WebGL build
#endif
#endif

17
src/Magnum/Implementation/TextureState.cpp

@ -387,12 +387,29 @@ TextureState::TextureState(Context& context, std::vector<std::string>& extension
glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxTextureUnits);
CORRADE_INTERNAL_ASSERT(maxTextureUnits > 0);
bindings = Containers::Array<std::pair<GLenum, GLuint>>{Containers::ValueInit, std::size_t(maxTextureUnits)};
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
/* Allocate image bindings array to hold all possible image units */
#ifndef MAGNUM_TARGET_GLES
if(context.isExtensionSupported<Extensions::GL::ARB::shader_image_load_store>())
#else
if(context.isVersionSupported(Version::GLES310))
#endif
{
GLint maxImageUnits;
glGetIntegerv(GL_MAX_IMAGE_UNITS, &maxImageUnits);
imageBindings = Containers::Array<std::tuple<GLuint, GLint, GLboolean, GLint, GLenum>>{Containers::ValueInit, std::size_t(maxImageUnits)};
}
#endif
}
TextureState::~TextureState() = default;
void TextureState::reset() {
std::fill_n(bindings.begin(), bindings.size(), std::pair<GLenum, GLuint>{{}, State::DisengagedBinding});
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
std::fill_n(imageBindings.begin(), imageBindings.size(), std::tuple<GLuint, GLint, GLboolean, GLint, GLenum>{State::DisengagedBinding, 0, false, 0, 0});
#endif
}
}}

4
src/Magnum/Implementation/TextureState.h

@ -27,6 +27,7 @@
#include <string>
#include <vector>
#include <Corrade/Containers/Array.h>
#include "Magnum/CubeMapTexture.h"
@ -140,6 +141,9 @@ struct TextureState {
#endif
Containers::Array<std::pair<GLenum, GLuint>> bindings;
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
Containers::Array<std::tuple<GLuint, GLint, GLboolean, GLint, GLenum>> imageBindings;
#endif
};
}}

5
src/Magnum/Magnum.h

@ -486,6 +486,11 @@ class CubeMapTextureArray;
class Extension;
class Framebuffer;
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
enum class ImageFormat: GLenum;
enum class ImageAccess: GLenum;
#endif
template<UnsignedInt> class Image;
typedef Image<1> Image1D;
typedef Image<2> Image2D;

76
src/Magnum/MultisampleTexture.h

@ -160,6 +160,82 @@ template<UnsignedInt dimensions> class MultisampleTexture: public AbstractTextur
*/
explicit MultisampleTexture(NoCreateT) noexcept: AbstractTexture{NoCreate, Implementation::multisampleTextureTarget<dimensions>()} {}
/**
* @brief Bind texture to given image unit
* @param imageUnit Image unit
* @param access Image access
* @param format Image format
*
* Available only on 2D multisample textures.
* @note This function is meant to be used only internally from
* @ref AbstractShaderProgram subclasses. See its documentation
* for more information.
* @see @ref bindImages(Int, std::initializer_list<AbstractTexture*>),
* @ref bindImageLayered(), @ref unbindImage(), @ref unbindImages(),
* @ref AbstractShaderProgram::maxImageUnits(),
* @fn_gl{BindImageTexture}
* @requires_gl42 Extension @extension{ARB,shader_image_load_store}
*/
#ifndef DOXYGEN_GENERATING_OUTPUT
template<UnsignedInt d = dimensions, class = typename std::enable_if<d == 2>::type>
#endif
void bindImage(Int imageUnit, ImageAccess access, ImageFormat format) {
bindImageInternal(imageUnit, 0, false, 0, access, format);
}
/**
* @brief Bind texture layer to given image unit
* @param imageUnit Image unit
* @param layer Texture layer
* @param access Image access
* @param format Image format
*
* Available only on 2D multisample texture arrays.
* @note This function is meant to be used only internally from
* @ref AbstractShaderProgram subclasses. See its documentation
* for more information.
* @see @ref bindImages(Int, std::initializer_list<AbstractTexture*>),
* @ref bindImageLayered(), @ref unbindImage(), @ref unbindImages(),
* @ref AbstractShaderProgram::maxImageUnits(),
* @fn_gl{BindImageTexture}
* @requires_gl42 Extension @extension{ARB,shader_image_load_store}
* @requires_es_extension Extension @es_extension{ANDROID,extension_pack_es31a}/
* @es_extension{OES,texture_storage_multisample_2d_array} for
* multisample 2D array textures.
*/
#ifndef DOXYGEN_GENERATING_OUTPUT
template<UnsignedInt d = dimensions, class = typename std::enable_if<d == 3>::type>
#endif
void bindImage(Int imageUnit, Int layer, ImageAccess access, ImageFormat format) {
bindImageInternal(imageUnit, 0, false, layer, access, format);
}
/**
* @brief Bind layered texture to given image unit
* @param imageUnit Image unit
* @param access Image access
* @param format Image format
*
* Available only on 2D multisample texture arrays.
* @note This function is meant to be used only internally from
* @ref AbstractShaderProgram subclasses. See its documentation
* for more information.
* @see @ref bindImages(Int, std::initializer_list<AbstractTexture*>),
* @ref bindImage(), @ref unbindImages(), @ref unbindImage(),
* @ref AbstractShaderProgram::maxImageUnits(),
* @fn_gl{BindImageTexture}
* @requires_gl42 Extension @extension{ARB,shader_image_load_store}
* @requires_es_extension Extension @es_extension{ANDROID,extension_pack_es31a}/
* @es_extension{OES,texture_storage_multisample_2d_array} for
* multisample 2D array textures.
*/
#ifndef DOXYGEN_GENERATING_OUTPUT
template<UnsignedInt d = dimensions, class = typename std::enable_if<d == 3>::type>
#endif
void bindImageLayered(Int imageUnit, ImageAccess access, ImageFormat format) {
bindImageInternal(imageUnit, 0, true, 0, access, format);
}
/**
* @brief Set storage
* @param samples Sample count

19
src/Magnum/RectangleTexture.h

@ -139,6 +139,25 @@ class MAGNUM_EXPORT RectangleTexture: public AbstractTexture {
*/
explicit RectangleTexture(NoCreateT) noexcept: AbstractTexture{NoCreate, GL_TEXTURE_RECTANGLE} {}
/**
* @brief Bind texture to given image unit
* @param imageUnit Image unit
* @param access Image access
* @param format Image format
*
* @note This function is meant to be used only internally from
* @ref AbstractShaderProgram subclasses. See its documentation
* for more information.
* @see @ref bindImages(Int, std::initializer_list<AbstractTexture*>),
* @ref unbindImage(), @ref unbindImages(),
* @ref AbstractShaderProgram::maxImageUnits(),
* @fn_gl{BindImageTexture}
* @requires_gl42 Extension @extension{ARB,shader_image_load_store}
*/
void bindImage(Int imageUnit, ImageAccess access, ImageFormat format) {
bindImageInternal(imageUnit, 0, false, 0, access, format);
}
/**
* @copybrief Texture::setMinificationFilter()
* @return Reference to self (for method chaining)

42
src/Magnum/Test/BufferTextureGLTest.cpp

@ -28,6 +28,7 @@
#include "Magnum/Buffer.h"
#include "Magnum/BufferTexture.h"
#include "Magnum/BufferTextureFormat.h"
#include "Magnum/ImageFormat.h"
#include "Magnum/Test/AbstractOpenGLTester.h"
namespace Magnum { namespace Test {
@ -40,6 +41,8 @@ struct BufferTextureGLTest: AbstractOpenGLTester {
void wrap();
void bind();
void bindImage();
void setBuffer();
void setBufferOffset();
};
@ -50,6 +53,8 @@ BufferTextureGLTest::BufferTextureGLTest() {
&BufferTextureGLTest::wrap,
&BufferTextureGLTest::bind,
&BufferTextureGLTest::bindImage,
&BufferTextureGLTest::setBuffer,
&BufferTextureGLTest::setBufferOffset});
}
@ -134,6 +139,43 @@ void BufferTextureGLTest::bind() {
MAGNUM_VERIFY_NO_ERROR();
}
void BufferTextureGLTest::bindImage() {
#ifndef MAGNUM_TARGET_GLES
if(!Context::current().isExtensionSupported<Extensions::GL::ARB::texture_buffer_object>())
CORRADE_SKIP(Extensions::GL::ARB::texture_buffer_object::string() + std::string(" is not supported."));
if(!Context::current().isExtensionSupported<Extensions::GL::ARB::shader_image_load_store>())
CORRADE_SKIP(Extensions::GL::ARB::shader_image_load_store::string() + std::string(" is not supported."));
#else
if(!Context::current().isExtensionSupported<Extensions::GL::EXT::texture_buffer>())
CORRADE_SKIP(Extensions::GL::EXT::texture_buffer::string() + std::string(" is not supported."));
if(!Context::current().isVersionSupported(Version::GLES310))
CORRADE_SKIP("OpenGL ES 3.1 is not supported.");
#endif
Buffer buffer;
buffer.setData({nullptr, 32}, BufferUsage::StaticDraw);
BufferTexture texture;
texture.setBuffer(BufferTextureFormat::RGBA8, buffer)
.bindImage(2, ImageAccess::ReadWrite, ImageFormat::RGBA8);
MAGNUM_VERIFY_NO_ERROR();
AbstractTexture::unbindImage(2);
MAGNUM_VERIFY_NO_ERROR();
#ifndef MAGNUM_TARGET_GLES
AbstractTexture::bindImages(1, {&texture, nullptr, &texture});
MAGNUM_VERIFY_NO_ERROR();
AbstractTexture::unbindImages(1, 3);
MAGNUM_VERIFY_NO_ERROR();
#endif
}
void BufferTextureGLTest::setBuffer() {
#ifndef MAGNUM_TARGET_GLES
if(!Context::current().isExtensionSupported<Extensions::GL::ARB::texture_buffer_object>())

40
src/Magnum/Test/CubeMapTextureArrayGLTest.cpp

@ -28,6 +28,7 @@
#include "Magnum/BufferImage.h"
#include "Magnum/CubeMapTextureArray.h"
#include "Magnum/Image.h"
#include "Magnum/ImageFormat.h"
#include "Magnum/PixelFormat.h"
#include "Magnum/TextureFormat.h"
#include "Magnum/Math/Color.h"
@ -44,6 +45,7 @@ struct CubeMapTextureArrayGLTest: AbstractOpenGLTester {
void wrap();
void bind();
void bindImage();
void sampling();
void samplingSRGBDecode();
@ -89,6 +91,7 @@ CubeMapTextureArrayGLTest::CubeMapTextureArrayGLTest() {
&CubeMapTextureArrayGLTest::wrap,
&CubeMapTextureArrayGLTest::bind,
&CubeMapTextureArrayGLTest::bindImage,
&CubeMapTextureArrayGLTest::sampling,
&CubeMapTextureArrayGLTest::samplingSRGBDecode,
@ -226,6 +229,43 @@ void CubeMapTextureArrayGLTest::bind() {
MAGNUM_VERIFY_NO_ERROR();
}
void CubeMapTextureArrayGLTest::bindImage() {
#ifndef MAGNUM_TARGET_GLES
if(!Context::current().isExtensionSupported<Extensions::GL::ARB::texture_cube_map_array>())
CORRADE_SKIP(Extensions::GL::ARB::texture_cube_map_array::string() + std::string(" is not supported."));
if(!Context::current().isExtensionSupported<Extensions::GL::ARB::shader_image_load_store>())
CORRADE_SKIP(Extensions::GL::ARB::shader_image_load_store::string() + std::string(" is not supported."));
#else
if(!Context::current().isExtensionSupported<Extensions::GL::EXT::texture_cube_map_array>())
CORRADE_SKIP(Extensions::GL::EXT::texture_cube_map_array::string() + std::string(" is not supported."));
if(!Context::current().isVersionSupported(Version::GLES310))
CORRADE_SKIP("OpenGL ES 3.1 is not supported.");
#endif
CubeMapTextureArray texture;
texture.setStorage(1, TextureFormat::RGBA8, {32, 32, 12})
.bindImage(2, 0, 1, ImageAccess::ReadWrite, ImageFormat::RGBA8);
MAGNUM_VERIFY_NO_ERROR();
texture.bindImageLayered(3, 0, ImageAccess::ReadWrite, ImageFormat::RGBA8);
AbstractTexture::unbindImage(2);
AbstractTexture::unbindImage(3);
MAGNUM_VERIFY_NO_ERROR();
#ifndef MAGNUM_TARGET_GLES
AbstractTexture::bindImages(1, {&texture, nullptr, &texture});
MAGNUM_VERIFY_NO_ERROR();
AbstractTexture::unbindImages(1, 3);
MAGNUM_VERIFY_NO_ERROR();
#endif
}
void CubeMapTextureArrayGLTest::sampling() {
#ifndef MAGNUM_TARGET_GLES
if(!Context::current().isExtensionSupported<Extensions::GL::ARB::texture_cube_map_array>())

44
src/Magnum/Test/CubeMapTextureGLTest.cpp

@ -31,6 +31,9 @@
#endif
#include "Magnum/CubeMapTexture.h"
#include "Magnum/Image.h"
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
#include "Magnum/ImageFormat.h"
#endif
#include "Magnum/PixelFormat.h"
#include "Magnum/TextureFormat.h"
#include "Magnum/Math/Color.h"
@ -47,6 +50,9 @@ struct CubeMapTextureGLTest: AbstractOpenGLTester {
void wrap();
void bind();
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
void bindImage();
#endif
void sampling();
void samplingSRGBDecode();
@ -116,6 +122,9 @@ CubeMapTextureGLTest::CubeMapTextureGLTest() {
&CubeMapTextureGLTest::wrap,
&CubeMapTextureGLTest::bind,
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
&CubeMapTextureGLTest::bindImage,
#endif
&CubeMapTextureGLTest::sampling,
&CubeMapTextureGLTest::samplingSRGBDecode,
@ -268,6 +277,41 @@ void CubeMapTextureGLTest::bind() {
MAGNUM_VERIFY_NO_ERROR();
}
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
void CubeMapTextureGLTest::bindImage() {
#ifndef MAGNUM_TARGET_GLES
if(!Context::current().isExtensionSupported<Extensions::GL::ARB::shader_image_load_store>())
CORRADE_SKIP(Extensions::GL::ARB::shader_image_load_store::string() + std::string(" is not supported."));
#else
if(!Context::current().isVersionSupported(Version::GLES310))
CORRADE_SKIP("OpenGL ES 3.1 is not supported.");
#endif
CubeMapTexture texture;
texture.setStorage(1, TextureFormat::RGBA8, Vector2i{32})
.bindImage(2, 0, CubeMapTexture::Coordinate::NegativeX, ImageAccess::ReadWrite, ImageFormat::RGBA8);
MAGNUM_VERIFY_NO_ERROR();
texture.bindImageLayered(3, 0, ImageAccess::ReadWrite, ImageFormat::RGBA8);
AbstractTexture::unbindImage(2);
AbstractTexture::unbindImage(3);
MAGNUM_VERIFY_NO_ERROR();
#ifndef MAGNUM_TARGET_GLES
AbstractTexture::bindImages(1, {&texture, nullptr, &texture});
MAGNUM_VERIFY_NO_ERROR();
AbstractTexture::unbindImages(1, 3);
MAGNUM_VERIFY_NO_ERROR();
#endif
}
#endif
void CubeMapTextureGLTest::sampling() {
CubeMapTexture texture;
texture.setMinificationFilter(Sampler::Filter::Linear, Sampler::Mipmap::Linear)

78
src/Magnum/Test/MultisampleTextureGLTest.cpp

@ -26,6 +26,7 @@
#include <Corrade/TestSuite/Compare/Container.h>
#include "Magnum/MultisampleTexture.h"
#include "Magnum/ImageFormat.h"
#include "Magnum/TextureFormat.h"
#include "Magnum/Math/Vector3.h"
#include "Magnum/Test/AbstractOpenGLTester.h"
@ -47,6 +48,9 @@ struct MultisampleTextureGLTest: AbstractOpenGLTester {
void bind2D();
void bind2DArray();
void bindImage2D();
void bindImage2DArray();
void storage2D();
void storage2DArray();
@ -70,6 +74,9 @@ MultisampleTextureGLTest::MultisampleTextureGLTest() {
&MultisampleTextureGLTest::bind2D,
&MultisampleTextureGLTest::bind2DArray,
&MultisampleTextureGLTest::bindImage2D,
&MultisampleTextureGLTest::bindImage2DArray,
&MultisampleTextureGLTest::storage2D,
&MultisampleTextureGLTest::storage2DArray,
@ -240,6 +247,77 @@ void MultisampleTextureGLTest::bind2DArray() {
MAGNUM_VERIFY_NO_ERROR();
}
void MultisampleTextureGLTest::bindImage2D() {
#ifndef MAGNUM_TARGET_GLES
if(!Context::current().isExtensionSupported<Extensions::GL::ARB::texture_multisample>())
CORRADE_SKIP(Extensions::GL::ARB::texture_multisample::string() + std::string(" is not supported."));
if(!Context::current().isExtensionSupported<Extensions::GL::ARB::shader_image_load_store>())
CORRADE_SKIP(Extensions::GL::ARB::shader_image_load_store::string() + std::string(" is not supported."));
#else
if(!Context::current().isExtensionSupported<Extensions::GL::OES::texture_storage_multisample_2d_array>())
CORRADE_SKIP(Extensions::GL::OES::texture_storage_multisample_2d_array::string() + std::string(" is not supported."));
if(!Context::current().isVersionSupported(Version::GLES310))
CORRADE_SKIP("OpenGL ES 3.1 is not supported.");
#endif
MultisampleTexture2D texture;
texture.setStorage(4, TextureFormat::RGBA8, Vector2i{32})
.bindImage(2, ImageAccess::ReadWrite, ImageFormat::RGBA8);
MAGNUM_VERIFY_NO_ERROR();
AbstractTexture::unbindImage(2);
MAGNUM_VERIFY_NO_ERROR();
#ifndef MAGNUM_TARGET_GLES
AbstractTexture::bindImages(1, {&texture, nullptr, &texture});
MAGNUM_VERIFY_NO_ERROR();
AbstractTexture::unbindImages(1, 3);
MAGNUM_VERIFY_NO_ERROR();
#endif
}
void MultisampleTextureGLTest::bindImage2DArray() {
#ifndef MAGNUM_TARGET_GLES
if(!Context::current().isExtensionSupported<Extensions::GL::ARB::texture_multisample>())
CORRADE_SKIP(Extensions::GL::ARB::texture_multisample::string() + std::string(" is not supported."));
if(!Context::current().isExtensionSupported<Extensions::GL::ARB::shader_image_load_store>())
CORRADE_SKIP(Extensions::GL::ARB::shader_image_load_store::string() + std::string(" is not supported."));
#else
if(!Context::current().isExtensionSupported<Extensions::GL::OES::texture_storage_multisample_2d_array>())
CORRADE_SKIP(Extensions::GL::OES::texture_storage_multisample_2d_array::string() + std::string(" is not supported."));
if(!Context::current().isVersionSupported(Version::GLES310))
CORRADE_SKIP("OpenGL ES 3.1 is not supported.");
#endif
MultisampleTexture2DArray texture;
texture.setStorage(4, TextureFormat::RGBA8, {32, 32, 4})
.bindImage(2, 1, ImageAccess::ReadWrite, ImageFormat::RGBA8);
MAGNUM_VERIFY_NO_ERROR();
texture.bindImageLayered(3, ImageAccess::ReadWrite, ImageFormat::RGBA8);
AbstractTexture::unbindImage(2);
AbstractTexture::unbindImage(3);
MAGNUM_VERIFY_NO_ERROR();
#ifndef MAGNUM_TARGET_GLES
AbstractTexture::bindImages(1, {&texture, nullptr, &texture});
MAGNUM_VERIFY_NO_ERROR();
AbstractTexture::unbindImages(1, 3);
MAGNUM_VERIFY_NO_ERROR();
#endif
}
void MultisampleTextureGLTest::storage2D() {
#ifndef MAGNUM_TARGET_GLES
if(!Context::current().isExtensionSupported<Extensions::GL::ARB::texture_multisample>())

28
src/Magnum/Test/RectangleTextureGLTest.cpp

@ -29,6 +29,7 @@
#include "Magnum/configure.h"
#include "Magnum/BufferImage.h"
#include "Magnum/Image.h"
#include "Magnum/ImageFormat.h"
#include "Magnum/PixelFormat.h"
#include "Magnum/RectangleTexture.h"
#include "Magnum/TextureFormat.h"
@ -46,6 +47,7 @@ struct RectangleTextureGLTest: AbstractOpenGLTester {
void wrap();
void bind();
void bindImage();
void sampling();
void samplingSRGBDecode();
@ -78,6 +80,7 @@ RectangleTextureGLTest::RectangleTextureGLTest() {
&RectangleTextureGLTest::wrap,
&RectangleTextureGLTest::bind,
&RectangleTextureGLTest::bindImage,
&RectangleTextureGLTest::sampling,
&RectangleTextureGLTest::samplingSRGBDecode,
@ -177,6 +180,31 @@ void RectangleTextureGLTest::bind() {
MAGNUM_VERIFY_NO_ERROR();
}
void RectangleTextureGLTest::bindImage() {
if(!Context::current().isExtensionSupported<Extensions::GL::ARB::texture_rectangle>())
CORRADE_SKIP(Extensions::GL::ARB::texture_rectangle::string() + std::string(" is not supported."));
if(!Context::current().isExtensionSupported<Extensions::GL::ARB::shader_image_load_store>())
CORRADE_SKIP(Extensions::GL::ARB::shader_image_load_store::string() + std::string(" is not supported."));
RectangleTexture texture;
texture.setStorage(TextureFormat::RGBA8, Vector2i{32})
.bindImage(2, ImageAccess::ReadWrite, ImageFormat::RGBA8);
MAGNUM_VERIFY_NO_ERROR();
AbstractTexture::unbindImage(2);
MAGNUM_VERIFY_NO_ERROR();
AbstractTexture::bindImages(1, {&texture, nullptr, &texture});
MAGNUM_VERIFY_NO_ERROR();
AbstractTexture::unbindImages(1, 3);
MAGNUM_VERIFY_NO_ERROR();
}
void RectangleTextureGLTest::sampling() {
if(!Context::current().isExtensionSupported<Extensions::GL::ARB::texture_rectangle>())
CORRADE_SKIP(Extensions::GL::ARB::texture_rectangle::string() + std::string(" is not supported."));

78
src/Magnum/Test/TextureArrayGLTest.cpp

@ -28,6 +28,7 @@
#include "Magnum/configure.h"
#include "Magnum/BufferImage.h"
#include "Magnum/Image.h"
#include "Magnum/ImageFormat.h"
#include "Magnum/PixelFormat.h"
#include "Magnum/TextureArray.h"
#include "Magnum/TextureFormat.h"
@ -57,6 +58,13 @@ struct TextureArrayGLTest: AbstractOpenGLTester {
#endif
void bind2D();
#ifndef MAGNUM_TARGET_WEBGL
#ifndef MAGNUM_TARGET_GLES
void bindImage1D();
#endif
void bindImage2D();
#endif
#ifndef MAGNUM_TARGET_GLES
void sampling1D();
#endif
@ -172,6 +180,13 @@ TextureArrayGLTest::TextureArrayGLTest() {
#endif
&TextureArrayGLTest::bind2D,
#ifndef MAGNUM_TARGET_WEBGL
#ifndef MAGNUM_TARGET_GLES
&TextureArrayGLTest::bindImage1D,
#endif
&TextureArrayGLTest::bindImage2D,
#endif
#ifndef MAGNUM_TARGET_GLES
&TextureArrayGLTest::sampling1D,
#endif
@ -424,6 +439,69 @@ void TextureArrayGLTest::bind2D() {
MAGNUM_VERIFY_NO_ERROR();
}
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
#ifndef MAGNUM_TARGET_GLES
void TextureArrayGLTest::bindImage1D() {
if(!Context::current().isExtensionSupported<Extensions::GL::ARB::shader_image_load_store>())
CORRADE_SKIP(Extensions::GL::ARB::shader_image_load_store::string() + std::string(" is not supported."));
Texture1DArray texture;
texture.setStorage(1, TextureFormat::RGBA8, {32, 4})
.bindImage(2, 0, 1, ImageAccess::ReadWrite, ImageFormat::RGBA8);
MAGNUM_VERIFY_NO_ERROR();
texture.bindImageLayered(3, 0, ImageAccess::ReadWrite, ImageFormat::RGBA8);
AbstractTexture::unbindImage(2);
AbstractTexture::unbindImage(3);
MAGNUM_VERIFY_NO_ERROR();
AbstractTexture::bindImages(1, {&texture, nullptr, &texture});
MAGNUM_VERIFY_NO_ERROR();
AbstractTexture::unbindImages(1, 3);
MAGNUM_VERIFY_NO_ERROR();
}
#endif
void TextureArrayGLTest::bindImage2D() {
#ifndef MAGNUM_TARGET_GLES
if(!Context::current().isExtensionSupported<Extensions::GL::ARB::shader_image_load_store>())
CORRADE_SKIP(Extensions::GL::ARB::shader_image_load_store::string() + std::string(" is not supported."));
#else
if(!Context::current().isVersionSupported(Version::GLES310))
CORRADE_SKIP("OpenGL ES 3.1 is not supported.");
#endif
Texture2DArray texture;
texture.setStorage(1, TextureFormat::RGBA8, {32, 32, 4})
.bindImage(2, 0, 1, ImageAccess::ReadWrite, ImageFormat::RGBA8);
MAGNUM_VERIFY_NO_ERROR();
texture.bindImageLayered(3, 0, ImageAccess::ReadWrite, ImageFormat::RGBA8);
AbstractTexture::unbindImage(2);
AbstractTexture::unbindImage(3);
MAGNUM_VERIFY_NO_ERROR();
#ifndef MAGNUM_TARGET_GLES
AbstractTexture::bindImages(1, {&texture, nullptr, &texture});
MAGNUM_VERIFY_NO_ERROR();
AbstractTexture::unbindImages(1, 3);
MAGNUM_VERIFY_NO_ERROR();
#endif
}
#endif
#ifndef MAGNUM_TARGET_GLES
void TextureArrayGLTest::sampling1D() {
if(!Context::current().isExtensionSupported<Extensions::GL::EXT::texture_array>())

109
src/Magnum/Test/TextureGLTest.cpp

@ -30,6 +30,9 @@
#include "Magnum/BufferImage.h"
#endif
#include "Magnum/Image.h"
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
#include "Magnum/ImageFormat.h"
#endif
#include "Magnum/PixelFormat.h"
#include "Magnum/Texture.h"
#include "Magnum/TextureFormat.h"
@ -63,6 +66,14 @@ struct TextureGLTest: AbstractOpenGLTester {
void bind2D();
void bind3D();
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
#ifndef MAGNUM_TARGET_GLES
void bindImage1D();
#endif
void bindImage2D();
void bindImage3D();
#endif
#ifndef MAGNUM_TARGET_GLES
void sampling1D();
#endif
@ -218,6 +229,14 @@ TextureGLTest::TextureGLTest() {
&TextureGLTest::bind2D,
&TextureGLTest::bind3D,
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
#ifndef MAGNUM_TARGET_GLES
&TextureGLTest::bindImage1D,
#endif
&TextureGLTest::bindImage2D,
&TextureGLTest::bindImage3D,
#endif
#ifndef MAGNUM_TARGET_GLES
&TextureGLTest::sampling1D,
#endif
@ -573,6 +592,96 @@ void TextureGLTest::bind3D() {
MAGNUM_VERIFY_NO_ERROR();
}
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
#ifndef MAGNUM_TARGET_GLES
void TextureGLTest::bindImage1D() {
if(!Context::current().isExtensionSupported<Extensions::GL::ARB::shader_image_load_store>())
CORRADE_SKIP(Extensions::GL::ARB::shader_image_load_store::string() + std::string(" is not supported."));
Texture1D texture;
texture.setStorage(1, TextureFormat::RGBA8, 32)
.bindImage(2, 0, ImageAccess::ReadWrite, ImageFormat::RGBA8);
MAGNUM_VERIFY_NO_ERROR();
AbstractTexture::unbindImage(2);
MAGNUM_VERIFY_NO_ERROR();
AbstractTexture::bindImages(1, {&texture, nullptr, &texture});
MAGNUM_VERIFY_NO_ERROR();
AbstractTexture::unbindImages(1, 3);
MAGNUM_VERIFY_NO_ERROR();
}
#endif
void TextureGLTest::bindImage2D() {
#ifndef MAGNUM_TARGET_GLES
if(!Context::current().isExtensionSupported<Extensions::GL::ARB::shader_image_load_store>())
CORRADE_SKIP(Extensions::GL::ARB::shader_image_load_store::string() + std::string(" is not supported."));
#else
if(!Context::current().isVersionSupported(Version::GLES310))
CORRADE_SKIP("OpenGL ES 3.1 is not supported.");
#endif
Texture2D texture;
texture.setStorage(1, TextureFormat::RGBA8, Vector2i{32})
.bindImage(2, 0, ImageAccess::ReadWrite, ImageFormat::RGBA8);
MAGNUM_VERIFY_NO_ERROR();
AbstractTexture::unbindImage(2);
MAGNUM_VERIFY_NO_ERROR();
#ifndef MAGNUM_TARGET_GLES
AbstractTexture::bindImages(1, {&texture, nullptr, &texture});
MAGNUM_VERIFY_NO_ERROR();
AbstractTexture::unbindImages(1, 3);
MAGNUM_VERIFY_NO_ERROR();
#endif
}
void TextureGLTest::bindImage3D() {
#ifndef MAGNUM_TARGET_GLES
if(!Context::current().isExtensionSupported<Extensions::GL::ARB::shader_image_load_store>())
CORRADE_SKIP(Extensions::GL::ARB::shader_image_load_store::string() + std::string(" is not supported."));
#else
if(!Context::current().isVersionSupported(Version::GLES310))
CORRADE_SKIP("OpenGL ES 3.1 is not supported.");
#endif
Texture3D texture;
texture.setStorage(1, TextureFormat::RGBA8, {32, 32, 4})
.bindImage(2, 0, 1, ImageAccess::ReadWrite, ImageFormat::RGBA8);
MAGNUM_VERIFY_NO_ERROR();
texture.bindImageLayered(3, 0, ImageAccess::ReadWrite, ImageFormat::RGBA8);
AbstractTexture::unbindImage(2);
AbstractTexture::unbindImage(3);
MAGNUM_VERIFY_NO_ERROR();
#ifndef MAGNUM_TARGET_GLES
AbstractTexture::bindImages(1, {&texture, nullptr, &texture});
MAGNUM_VERIFY_NO_ERROR();
AbstractTexture::unbindImages(1, 3);
MAGNUM_VERIFY_NO_ERROR();
#endif
}
#endif
#ifndef MAGNUM_TARGET_GLES
void TextureGLTest::sampling1D() {
Texture1D texture;

84
src/Magnum/Texture.h

@ -194,6 +194,90 @@ template<UnsignedInt dimensions> class Texture: public AbstractTexture {
*/
explicit Texture(NoCreateT) noexcept: AbstractTexture{NoCreate, Implementation::textureTarget<dimensions>()} {}
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
/**
* @brief Bind level of texture to given image unit
* @param imageUnit Image unit
* @param level Texture level
* @param access Image access
* @param format Image format
*
* Available only on 1D and 2D textures.
* @note This function is meant to be used only internally from
* @ref AbstractShaderProgram subclasses. See its documentation
* for more information.
* @see @ref bindImages(Int, std::initializer_list<AbstractTexture*>),
* @ref bindImageLayered(), @ref unbindImage(), @ref unbindImages(),
* @ref AbstractShaderProgram::maxImageUnits(),
* @fn_gl{BindImageTexture}
* @requires_gl42 Extension @extension{ARB,shader_image_load_store}
* @requires_gles31 Shader image load/store is not available in OpenGL
* ES 3.0 and older.
* @requires_gles Shader image load/store is not available in WebGL.
*/
#ifndef DOXYGEN_GENERATING_OUTPUT
template<UnsignedInt d = dimensions, class = typename std::enable_if<d == 1 || d == 2>::type>
#endif
void bindImage(Int imageUnit, Int level, ImageAccess access, ImageFormat format) {
bindImageInternal(imageUnit, level, false, 0, access, format);
}
/**
* @brief Bind level of given texture layer to given image unit
* @param imageUnit Image unit
* @param level Texture level
* @param layer Texture layer
* @param access Image access
* @param format Image format
*
* Available only on 3D textures.
* @note This function is meant to be used only internally from
* @ref AbstractShaderProgram subclasses. See its documentation
* for more information.
* @see @ref bindImages(Int, std::initializer_list<AbstractTexture*>),
* @ref bindImageLayered(), @ref unbindImage(), @ref unbindImages(),
* @ref AbstractShaderProgram::maxImageUnits(),
* @fn_gl{BindImageTexture}
* @requires_gl42 Extension @extension{ARB,shader_image_load_store}
* @requires_gles31 Shader image load/store is not available in OpenGL
* ES 3.0 and older.
* @requires_gles Shader image load/store is not available in WebGL.
*/
#ifndef DOXYGEN_GENERATING_OUTPUT
template<UnsignedInt d = dimensions, class = typename std::enable_if<d == 3>::type>
#endif
void bindImage(Int imageUnit, Int level, Int layer, ImageAccess access, ImageFormat format) {
bindImageInternal(imageUnit, level, false, layer, access, format);
}
/**
* @brief Bind level of layered texture to given image unit
* @param imageUnit Image unit
* @param level Texture level
* @param access Image access
* @param format Image format
*
* Available only on 3D textures.
* @note This function is meant to be used only internally from
* @ref AbstractShaderProgram subclasses. See its documentation
* for more information.
* @see @ref bindImages(Int, std::initializer_list<AbstractTexture*>),
* @ref bindImage(), @ref unbindImage(), @ref unbindImages(),
* @ref AbstractShaderProgram::maxImageUnits(),
* @fn_gl{BindImageTexture}
* @requires_gl42 Extension @extension{ARB,shader_image_load_store}
* @requires_gles31 Shader image load/store is not available in OpenGL
* ES 3.0 and older.
* @requires_gles Shader image load/store is not available in WebGL.
*/
#ifndef DOXYGEN_GENERATING_OUTPUT
template<UnsignedInt d = dimensions, class = typename std::enable_if<d == 3>::type>
#endif
void bindImageLayered(Int imageUnit, Int level, ImageAccess access, ImageFormat format) {
bindImageInternal(imageUnit, level, true, 0, access, format);
}
#endif
#ifndef MAGNUM_TARGET_GLES2
/**
* @brief Set base mip level

49
src/Magnum/TextureArray.h

@ -177,6 +177,55 @@ template<UnsignedInt dimensions> class TextureArray: public AbstractTexture {
*/
explicit TextureArray(NoCreateT) noexcept: AbstractTexture{NoCreate, Implementation::textureArrayTarget<dimensions>()} {}
#ifndef MAGNUM_TARGET_WEBGL
/**
* @brief Bind level of given texture layer to given image unit
* @param imageUnit Image unit
* @param level Texture level
* @param layer Texture layer
* @param access Image access
* @param format Image format
*
* @note This function is meant to be used only internally from
* @ref AbstractShaderProgram subclasses. See its documentation
* for more information.
* @see @ref bindImages(Int, std::initializer_list<AbstractTexture*>),
* @ref bindImageLayered(), @ref unbindImage(), @ref unbindImages(),
* @ref AbstractShaderProgram::maxImageUnits(),
* @fn_gl{BindImageTexture}
* @requires_gl42 Extension @extension{ARB,shader_image_load_store}
* @requires_gles31 Shader image load/store is not available in OpenGL
* ES 3.0 and older.
* @requires_gles Shader image load/store is not available in WebGL.
*/
void bindImage(Int imageUnit, Int level, Int layer, ImageAccess access, ImageFormat format) {
bindImageInternal(imageUnit, level, false, layer, access, format);
}
/**
* @brief Bind level of layered texture to given image unit
* @param imageUnit Image unit
* @param level Texture level
* @param access Image access
* @param format Image format
*
* @note This function is meant to be used only internally from
* @ref AbstractShaderProgram subclasses. See its documentation
* for more information.
* @see @ref bindImages(Int, std::initializer_list<AbstractTexture*>),
* @ref bindImage(), @ref unbindImage(), @ref unbindImages(),
* @ref AbstractShaderProgram::maxImageUnits(),
* @fn_gl{BindImageTexture}
* @requires_gl42 Extension @extension{ARB,shader_image_load_store}
* @requires_gles31 Shader image load/store is not available in OpenGL
* ES 3.0 and older.
* @requires_gles Shader image load/store is not available in WebGL.
*/
void bindImageLayered(Int imageUnit, Int level, ImageAccess access, ImageFormat format) {
bindImageInternal(imageUnit, level, true, 0, access, format);
}
#endif
/**
* @copybrief Texture::setBaseLevel()
* @return Reference to self (for method chaining)

Loading…
Cancel
Save