Browse Source

GL: reworked apple-buffer-texture-unbind-on-buffer-modify workaround.

Much smaller, nicer and more robust.
mousecapture
Vladimír Vondruš 6 years ago
parent
commit
24cc971b1f
  1. 6
      doc/changelog.dox
  2. 88
      src/Magnum/GL/Buffer.cpp
  3. 22
      src/Magnum/GL/Buffer.h
  4. 15
      src/Magnum/GL/BufferTexture.cpp
  5. 8
      src/Magnum/GL/BufferTexture.h
  6. 2
      src/Magnum/GL/Implementation/BufferState.cpp
  7. 9
      src/Magnum/GL/Implementation/TextureState.cpp
  8. 32
      src/Magnum/GL/Implementation/driverSpecific.cpp
  9. 97
      src/Magnum/GL/Test/BufferTextureGLTest.cpp

6
doc/changelog.dox

@ -65,10 +65,10 @@ See also:
that attempted to fix this by doing an explicit buffer binding in some that attempted to fix this by doing an explicit buffer binding in some
cases. See @ref opengl-workarounds and [mosra/magnum#405](https://github.com/mosra/magnum/pull/405) cases. See @ref opengl-workarounds and [mosra/magnum#405](https://github.com/mosra/magnum/pull/405)
for more information. for more information.
- A @cpp "apple-buffer-texture-detach-on-data-modify" @ce workaround that - A @cpp "apple-buffer-texture-unbind-on-buffer-modify" @ce workaround that
fixes crashes on Apple macOS when attempting to modify a @ref GL::Buffer fixes crashes on Apple macOS when attempting to modify a @ref GL::Buffer
that's attached to a @ref GL::BufferTexture. See @ref opengl-workarounds when a @ref GL::BufferTexture is bound. See @ref opengl-workarounds for
for more information. more information.
@subsubsection changelog-latest-new-math Math library @subsubsection changelog-latest-new-math Math library

88
src/Magnum/GL/Buffer.cpp

@ -29,9 +29,6 @@
#include <Corrade/Containers/Array.h> #include <Corrade/Containers/Array.h>
#include <Corrade/Utility/Debug.h> #include <Corrade/Utility/Debug.h>
#if defined(CORRADE_TARGET_APPLE) && !defined(CORRADE_TARGET_IOS)
#include "Magnum/GL/BufferTexture.h"
#endif
#include "Magnum/GL/Context.h" #include "Magnum/GL/Context.h"
#include "Magnum/GL/Extensions.h" #include "Magnum/GL/Extensions.h"
#include "Magnum/GL/Implementation/State.h" #include "Magnum/GL/Implementation/State.h"
@ -41,6 +38,10 @@
#endif #endif
#include "Magnum/GL/Implementation/MeshState.h" #include "Magnum/GL/Implementation/MeshState.h"
#if defined(CORRADE_TARGET_APPLE) && !defined(CORRADE_TARGET_IOS)
#include "Magnum/GL/Implementation/TextureState.h"
#endif
namespace Magnum { namespace GL { namespace Magnum { namespace GL {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
@ -550,88 +551,51 @@ bool Buffer::unmapImplementationDSA() {
#endif #endif
#if defined(CORRADE_TARGET_APPLE) && !defined(CORRADE_TARGET_IOS) #if defined(CORRADE_TARGET_APPLE) && !defined(CORRADE_TARGET_IOS)
/* If this buffer is attached to a buffer texture, we need to temporarily /* See apple-buffer-texture-detach-on-data-modify for the gory details. */
detach it to avoid crashes in the macOS driver when doing buffer-modifying
operations. See the apple-buffer-texture-detach-on-setdata workaround for
more info. */
void Buffer::textureWorkaroundAppleBefore() { void Buffer::textureWorkaroundAppleBefore() {
/* No buffer texture attached or the texture no longer exists, nothing to /* Apple "fortunately" supports just 16 texture units, so this doesn't take
do */ too long. */
if(!_bufferTexture || !glIsTexture(_bufferTexture)) { Implementation::TextureState& textureState = *Context::current().state().texture;
_bufferTexture = 0; /* Avoid doing unnecessary work next time */ for(GLint textureUnit = 0; textureUnit != GLint(textureState.bindings.size()); ++textureUnit) {
return; std::pair<GLenum, GLuint>& binding = textureState.bindings[textureUnit];
} if(binding.first != GL_TEXTURE_BUFFER) continue;
/* Bind the buffer texture so we can ask for its state (as there's no /* Activate given texture unit if not already active, update state
DSA on Apple to have a shortcut). The state tracking is a bit tracker */
complicated for textures, so playing it safe and using (friended) if(textureState.currentTextureUnit != textureUnit)
private AbstractTexture APIs for that. */ glActiveTexture(GL_TEXTURE0 + (textureState.currentTextureUnit = textureUnit));
BufferTexture t = BufferTexture::wrap(_bufferTexture);
t.bindInternal(); /* Unbind the texture, reset state tracker */
glBindTexture(GL_TEXTURE_BUFFER, 0);
/* Check the current buffer binding for the texture. If it is no longer /* libstdc++ since GCC 6.3 can't handle just = {} (ambiguous overload
our buffer, the buffer might get detached since or replaced with of operator=) */
another (which is fine, and much easier than maintaining the state binding = std::pair<GLenum, GLuint>{};
explicitly). */ }
GLuint currentBufferBinding;
glGetTexLevelParameteriv(GL_TEXTURE_BUFFER, 0, GL_TEXTURE_BUFFER_DATA_STORE_BINDING, reinterpret_cast<GLint*>(&currentBufferBinding));
if(currentBufferBinding != _id) {
_bufferTexture = 0; /* Avoid doing unnecessary work next time */
return;
}
/* In a saner bug workaround, i would just query
GL_TEXTURE_INTERNAL_FORMAT here. However, that's also broken,
returning GL_R8 always, so instead we have to cache it in the
Buffer instance. "Fortunately" macOS doesn't support
ARB_texture_range, so we don't need to store the offset + size,
just the format. */
CORRADE_INTERNAL_ASSERT(!Context::current().isExtensionSupported<Extensions::ARB::texture_buffer_range>());
/* Temporarily detach the buffer. To avoid hitting more corner
cases, keep the same format as before. */
glTexBuffer(GL_TEXTURE_BUFFER, _bufferTextureFormat, 0);
}
void Buffer::textureWorkaroundAppleAfter() {
/* Put the buffer back, if we are supposed to be attached to a texture.
Assumes textureWorkaroundAppleBefore() was called and thus the texture
is bound. In case the state was stale, _bufferTexture was set to 0, so
this will get executed only when needed. */
if(_bufferTexture) glTexBuffer(GL_TEXTURE_BUFFER, _bufferTextureFormat, _id);
} }
void Buffer::dataImplementationApple(const GLsizeiptr size, const GLvoid* const data, const BufferUsage usage) { void Buffer::dataImplementationApple(const GLsizeiptr size, const GLvoid* const data, const BufferUsage usage) {
textureWorkaroundAppleBefore(); textureWorkaroundAppleBefore();
dataImplementationDefault(size, data, usage); dataImplementationDefault(size, data, usage);
textureWorkaroundAppleAfter();
} }
void Buffer::subDataImplementationApple(const GLintptr offset, const GLsizeiptr size, const GLvoid* const data) { void Buffer::subDataImplementationApple(const GLintptr offset, const GLsizeiptr size, const GLvoid* const data) {
textureWorkaroundAppleBefore(); textureWorkaroundAppleBefore();
subDataImplementationDefault(offset, size, data); subDataImplementationDefault(offset, size, data);
textureWorkaroundAppleAfter();
} }
void* Buffer::mapImplementationApple(const MapAccess access) { void* Buffer::mapImplementationApple(const MapAccess access) {
textureWorkaroundAppleBefore(); textureWorkaroundAppleBefore();
void* const out = mapImplementationDefault(access); return mapImplementationDefault(access);
textureWorkaroundAppleAfter();
return out;
} }
void* Buffer::mapRangeImplementationApple(const GLintptr offset, const GLsizeiptr length, const MapFlags access) { void* Buffer::mapRangeImplementationApple(const GLintptr offset, const GLsizeiptr length, const MapFlags access) {
textureWorkaroundAppleBefore(); textureWorkaroundAppleBefore();
void* const out = mapRangeImplementationDefault(offset, length, access); return mapRangeImplementationDefault(offset, length, access);
textureWorkaroundAppleAfter();
return out;
} }
bool Buffer::unmapImplementationApple() { bool Buffer::unmapImplementationApple() {
textureWorkaroundAppleBefore(); textureWorkaroundAppleBefore();
const bool out = unmapImplementationDefault(); return unmapImplementationDefault();
textureWorkaroundAppleAfter();
return out;
} }
#endif #endif

22
src/Magnum/GL/Buffer.h

@ -1285,10 +1285,6 @@ class MAGNUM_GL_EXPORT Buffer: public AbstractObject {
GLuint _id; GLuint _id;
TargetHint _targetHint; TargetHint _targetHint;
ObjectFlags _flags; ObjectFlags _flags;
#if defined(CORRADE_TARGET_APPLE) && !defined(CORRADE_TARGET_IOS)
GLuint _bufferTexture{};
GLenum _bufferTextureFormat{};
#endif
}; };
#ifndef MAGNUM_TARGET_WEBGL #ifndef MAGNUM_TARGET_WEBGL
@ -1305,16 +1301,8 @@ MAGNUM_GL_EXPORT Debug& operator<<(Debug& debug, Buffer::Target value);
inline Buffer::Buffer(NoCreateT) noexcept: _id{0}, _targetHint{TargetHint::Array}, _flags{ObjectFlag::DeleteOnDestruction} {} inline Buffer::Buffer(NoCreateT) noexcept: _id{0}, _targetHint{TargetHint::Array}, _flags{ObjectFlag::DeleteOnDestruction} {}
inline Buffer::Buffer(Buffer&& other) noexcept: _id{other._id}, _targetHint{other._targetHint}, _flags{other._flags} inline Buffer::Buffer(Buffer&& other) noexcept: _id{other._id}, _targetHint{other._targetHint}, _flags{other._flags} {
#if defined(CORRADE_TARGET_APPLE) && !defined(CORRADE_TARGET_IOS)
, _bufferTexture{other._bufferTexture}, _bufferTextureFormat{other._bufferTextureFormat}
#endif
{
other._id = 0; other._id = 0;
#if defined(CORRADE_TARGET_APPLE) && !defined(CORRADE_TARGET_IOS)
other._bufferTexture = 0;
other._bufferTextureFormat = 0;
#endif
} }
inline Buffer& Buffer::operator=(Buffer&& other) noexcept { inline Buffer& Buffer::operator=(Buffer&& other) noexcept {
@ -1322,20 +1310,12 @@ inline Buffer& Buffer::operator=(Buffer&& other) noexcept {
swap(_id, other._id); swap(_id, other._id);
swap(_targetHint, other._targetHint); swap(_targetHint, other._targetHint);
swap(_flags, other._flags); swap(_flags, other._flags);
#if defined(CORRADE_TARGET_APPLE) && !defined(CORRADE_TARGET_IOS)
swap(_bufferTexture, other._bufferTexture);
swap(_bufferTextureFormat, other._bufferTextureFormat);
#endif
return *this; return *this;
} }
inline GLuint Buffer::release() { inline GLuint Buffer::release() {
const GLuint id = _id; const GLuint id = _id;
_id = 0; _id = 0;
#if defined(CORRADE_TARGET_APPLE) && !defined(CORRADE_TARGET_IOS)
_bufferTexture = 0;
_bufferTextureFormat = 0;
#endif
return id; return id;
} }

15
src/Magnum/GL/BufferTexture.cpp

@ -96,21 +96,6 @@ void BufferTexture::setBufferImplementationDefault(BufferTextureFormat internalF
glTexBuffer(GL_TEXTURE_BUFFER, GLenum(internalFormat), buffer ? buffer->id() : 0); glTexBuffer(GL_TEXTURE_BUFFER, GLenum(internalFormat), buffer ? buffer->id() : 0);
} }
#if defined(CORRADE_TARGET_APPLE) && !defined(CORRADE_TARGET_IOS)
void BufferTexture::setBufferImplementationApple(BufferTextureFormat internalFormat, Buffer* buffer) {
/* Reference this texture from the buffer so next time setData() is called
we can temporarily detach it. See apple-buffer-texture-detach-on-setdata
for more information. */
if(buffer) {
buffer->_bufferTexture = id();
buffer->_bufferTextureFormat = GLenum(internalFormat);
}
bindInternal();
glTexBuffer(GL_TEXTURE_BUFFER, GLenum(internalFormat), buffer ? buffer->id() : 0);
}
#endif
#ifdef MAGNUM_TARGET_GLES #ifdef MAGNUM_TARGET_GLES
void BufferTexture::setBufferImplementationEXT(BufferTextureFormat internalFormat, Buffer* buffer) { void BufferTexture::setBufferImplementationEXT(BufferTextureFormat internalFormat, Buffer* buffer) {
bindInternal(); bindInternal();

8
src/Magnum/GL/BufferTexture.h

@ -258,16 +258,10 @@ class MAGNUM_GL_EXPORT BufferTexture: public AbstractTexture {
private: private:
friend Implementation::TextureState; friend Implementation::TextureState;
#if defined(CORRADE_TARGET_APPLE) && !defined(CORRADE_TARGET_IOS)
friend Buffer;
#endif
explicit BufferTexture(GLuint id, ObjectFlags flags): AbstractTexture{id, GL_TEXTURE_BUFFER, flags} {} explicit BufferTexture(GLuint id, ObjectFlags flags): AbstractTexture{id, GL_TEXTURE_BUFFER, flags} {}
void MAGNUM_GL_LOCAL setBufferImplementationDefault(BufferTextureFormat internalFormat, Buffer* buffer); void MAGNUM_GL_LOCAL setBufferImplementationDefault(BufferTextureFormat internalFormat, Buffer* buffer);
#if defined(CORRADE_TARGET_APPLE) && !defined(CORRADE_TARGET_IOS)
void MAGNUM_GL_LOCAL setBufferImplementationApple(BufferTextureFormat internalFormat, Buffer* buffer);
#endif
#ifdef MAGNUM_TARGET_GLES #ifdef MAGNUM_TARGET_GLES
void MAGNUM_GL_LOCAL setBufferImplementationEXT(BufferTextureFormat internalFormat, Buffer* buffer); void MAGNUM_GL_LOCAL setBufferImplementationEXT(BufferTextureFormat internalFormat, Buffer* buffer);
#endif #endif
@ -276,8 +270,6 @@ class MAGNUM_GL_EXPORT BufferTexture: public AbstractTexture {
#endif #endif
void MAGNUM_GL_LOCAL setBufferRangeImplementationDefault(BufferTextureFormat internalFormat, Buffer& buffer, GLintptr offset, GLsizeiptr size); void MAGNUM_GL_LOCAL setBufferRangeImplementationDefault(BufferTextureFormat internalFormat, Buffer& buffer, GLintptr offset, GLsizeiptr size);
/* No need for Apple-specific setBufferRangeImplementation, as the
extension is not supported anyway */
#ifdef MAGNUM_TARGET_GLES #ifdef MAGNUM_TARGET_GLES
void MAGNUM_GL_LOCAL setBufferRangeImplementationEXT(BufferTextureFormat internalFormat, Buffer& buffer, GLintptr offset, GLsizeiptr size); void MAGNUM_GL_LOCAL setBufferRangeImplementationEXT(BufferTextureFormat internalFormat, Buffer& buffer, GLintptr offset, GLsizeiptr size);
#endif #endif

2
src/Magnum/GL/Implementation/BufferState.cpp

@ -178,7 +178,7 @@ BufferState::BufferState(Context& context, std::vector<std::string>& extensions)
} }
#if defined(CORRADE_TARGET_APPLE) && !defined(CORRADE_TARGET_IOS) #if defined(CORRADE_TARGET_APPLE) && !defined(CORRADE_TARGET_IOS)
if(!context.isDriverWorkaroundDisabled("apple-buffer-texture-detach-on-data-modify")) { if(!context.isDriverWorkaroundDisabled("apple-buffer-texture-unbind-on-buffer-modify")) {
dataImplementation = &Buffer::dataImplementationApple; dataImplementation = &Buffer::dataImplementationApple;
subDataImplementation = &Buffer::subDataImplementationApple; subDataImplementation = &Buffer::subDataImplementationApple;
mapImplementation = &Buffer::mapImplementationApple; mapImplementation = &Buffer::mapImplementationApple;

9
src/Magnum/GL/Implementation/TextureState.cpp

@ -483,15 +483,6 @@ TextureState::TextureState(Context& context, std::vector<std::string>& extension
} }
#endif #endif
#if defined(CORRADE_TARGET_APPLE) && !defined(CORRADE_TARGET_IOS)
if(!context.isDriverWorkaroundDisabled("apple-buffer-texture-detach-on-data-modify")) {
setBufferImplementation = &BufferTexture::setBufferImplementationApple;
/* No need for Apple-specific setBufferRangeImplementation, as the
extension is not supported anyway */
CORRADE_INTERNAL_ASSERT(!context.isExtensionSupported<Extensions::ARB::texture_buffer_range>());
}
#endif
/* Allocate texture bindings array to hold all possible texture units */ /* Allocate texture bindings array to hold all possible texture units */
glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxTextureUnits); glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxTextureUnits);
CORRADE_INTERNAL_ASSERT(maxTextureUnits > 0); CORRADE_INTERNAL_ASSERT(maxTextureUnits > 0);

32
src/Magnum/GL/Implementation/driverSpecific.cpp

@ -40,17 +40,27 @@ namespace {
/* [workarounds] */ /* [workarounds] */
#if defined(CORRADE_TARGET_APPLE) && !defined(CORRADE_TARGET_IOS) #if defined(CORRADE_TARGET_APPLE) && !defined(CORRADE_TARGET_IOS)
/* Calling glBufferData(), glMapBuffer(), glMapBufferRange() or glUnmapBuffer() /* Calling glBufferData(), glMapBuffer(), glMapBufferRange() or glUnmapBuffer()
on a buffer that's attached to a GL_TEXTURE_BUFFER crashes in on ANY buffer when ANY buffer is attached to a currently bound
gleUpdateCtxDirtyStateForBufStampChange deep inside Apple's GLengine. A GL_TEXTURE_BUFFER crashes in gleUpdateCtxDirtyStateForBufStampChange deep
workaround is to remember if a buffer is attached to a buffer texture, inside Apple's GLengine. This can be worked around by unbinding all buffer
temporarily detaching it, calling given data-modifying API and then textures before attempting to do such operation.
attaching it back with the same parameters. Unfortunately we need to cache
also the internal texture format, as GL_TEXTURE_INTERNAL_FORMAT query is A previous iteration of this workaround was to remember if a buffer is
broken for buffer textures as well, returning always GL_R8 (the attached to a buffer texture, temporarily detaching it, calling given
spec-mandated default). "Fortunately" macOS doesn't support data-modifying API and then attaching it back with the same parameters.
ARB_texture_buffer_range so we don't need to store also offset/size, only Unfortunately we also had to cache the internal texture format, as
texture ID and its internal format, wasting 8 bytes per Buffer instance. */ GL_TEXTURE_INTERNAL_FORMAT query is broken for buffer textures as well,
"apple-buffer-texture-detach-on-data-modify", returning always GL_R8 (the spec-mandated default). "Fortunately" macOS
doesn't support ARB_texture_buffer_range so we didn't need to store also
offset/size, only texture ID and its internal format, wasting 8 bytes per
Buffer instance. HOWEVER, then we discovered this is not enough and also
completely unrelated buffers suffer from the same crash. Fixing that
properly in a similar manner would mean going through all live buffer
texture instances and temporarily detaching their buffer when doing *any*
data modification on *any* buffer, which would have extreme perf
implications. So FORTUNATELY unbinding the textures worked around this too,
and is a much nicer workaround after all. */
"apple-buffer-texture-unbind-on-buffer-modify",
#endif #endif
#if defined(CORRADE_TARGET_ANDROID) && defined(MAGNUM_TARGET_GLES) #if defined(CORRADE_TARGET_ANDROID) && defined(MAGNUM_TARGET_GLES)

97
src/Magnum/GL/Test/BufferTextureGLTest.cpp

@ -57,9 +57,6 @@ struct BufferTextureGLTest: OpenGLTester {
void appleSetBufferQueryData(); void appleSetBufferQueryData();
void appleSetBufferMap(); void appleSetBufferMap();
void appleSetBufferMapRange(); void appleSetBufferMapRange();
void appleSetBufferDataMoved();
void appleSetBufferDataBufferDetached();
void appleSetBufferDataTextureDeleted();
#endif #endif
}; };
@ -81,10 +78,7 @@ BufferTextureGLTest::BufferTextureGLTest() {
&BufferTextureGLTest::appleSetUnrelatedBufferData, &BufferTextureGLTest::appleSetUnrelatedBufferData,
&BufferTextureGLTest::appleSetBufferQueryData, &BufferTextureGLTest::appleSetBufferQueryData,
&BufferTextureGLTest::appleSetBufferMap, &BufferTextureGLTest::appleSetBufferMap,
&BufferTextureGLTest::appleSetBufferMapRange, &BufferTextureGLTest::appleSetBufferMapRange
&BufferTextureGLTest::appleSetBufferDataMoved,
&BufferTextureGLTest::appleSetBufferDataBufferDetached,
&BufferTextureGLTest::appleSetBufferDataTextureDeleted
#endif #endif
}); });
} }
@ -461,95 +455,6 @@ void BufferTextureGLTest::appleSetBufferMapRange() {
MAGNUM_VERIFY_NO_GL_ERROR(); MAGNUM_VERIFY_NO_GL_ERROR();
} }
void BufferTextureGLTest::appleSetBufferDataMoved() {
#ifndef MAGNUM_TARGET_GLES
if(!Context::current().isExtensionSupported<Extensions::ARB::texture_buffer_object>())
CORRADE_SKIP(Extensions::ARB::texture_buffer_object::string() + std::string(" is not supported."));
#else
if(!Context::current().isExtensionSupported<Extensions::EXT::texture_buffer>())
CORRADE_SKIP(Extensions::EXT::texture_buffer::string() + std::string(" is not supported."));
#endif
BufferTexture texture;
Buffer a;
texture.setBuffer(BufferTextureFormat::RG8UI, a);
MAGNUM_VERIFY_NO_GL_ERROR();
if(Context::current().isVersionSupported(Version::GLES310))
CORRADE_COMPARE(texture.size(), 0);
/* Verify that the texture relation info survives moving the buffer */
a.setData<UnsignedByte>({
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
});
MAGNUM_VERIFY_NO_GL_ERROR();
CORRADE_COMPARE(texture.size(), 8);
Buffer b{std::move(a)};
b.setData<UnsignedByte>({0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f});
MAGNUM_VERIFY_NO_GL_ERROR();
CORRADE_COMPARE(texture.size(), 4);
Buffer c;
c = std::move(b);
c.setData<UnsignedByte>({
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
});
MAGNUM_VERIFY_NO_GL_ERROR();
CORRADE_COMPARE(texture.size(), 8);
}
void BufferTextureGLTest::appleSetBufferDataBufferDetached() {
if(!Context::current().isExtensionSupported<Extensions::ARB::texture_buffer_object>())
CORRADE_SKIP(Extensions::ARB::texture_buffer_object::string() + std::string(" is not supported."));
BufferTexture texture;
Buffer buffer;
buffer.setData<UnsignedByte>({
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
});
texture.setBuffer(BufferTextureFormat::RG8UI, buffer);
MAGNUM_VERIFY_NO_GL_ERROR();
CORRADE_COMPARE(texture.size(), 8);
texture.resetBuffer();
CORRADE_COMPARE(texture.size(), 0);
/* The buffer is no longer attached to the texture, so it should not
attempt to attach itself again */
buffer.setData<UnsignedByte>({0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f});
MAGNUM_VERIFY_NO_GL_ERROR();
CORRADE_COMPARE(texture.size(), 0);
}
void BufferTextureGLTest::appleSetBufferDataTextureDeleted() {
if(!Context::current().isExtensionSupported<Extensions::ARB::texture_buffer_object>())
CORRADE_SKIP(Extensions::ARB::texture_buffer_object::string() + std::string(" is not supported."));
Buffer buffer;
buffer.setData<UnsignedByte>({
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
});
{
BufferTexture texture;
texture.setBuffer(BufferTextureFormat::RG8UI, buffer);
MAGNUM_VERIFY_NO_GL_ERROR();
CORRADE_COMPARE(texture.size(), 8);
}
/* The texture no longer exists, so the buffer should not attempt to
access it */
buffer.setData<UnsignedByte>({0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f});
MAGNUM_VERIFY_NO_GL_ERROR();
}
#endif #endif
}}}} }}}}

Loading…
Cancel
Save