Browse Source

GL: yet another workaround for SwiftShader, now with XFB buffer bindings.

pull/324/head
Vladimír Vondruš 7 years ago
parent
commit
3d08c641d8
  1. 4
      doc/changelog.dox
  2. 27
      src/Magnum/GL/Buffer.cpp
  3. 12
      src/Magnum/GL/Buffer.h
  4. 11
      src/Magnum/GL/Implementation/BufferState.cpp
  5. 1
      src/Magnum/GL/Implementation/BufferState.h
  6. 10
      src/Magnum/GL/Implementation/driverSpecific.cpp

4
doc/changelog.dox

@ -60,6 +60,10 @@ See also:
disabling @gl_extension{ANGLE,instanced_arrays} and
@gl_extension{OES,texture_3D} extensions on SwiftShader due to missing
suffixed entry points. See @ref opengl-workarounds for more information.
- New @cpp "swiftshader-broken-xfb-buffer-binding-target" @ce workaround
that's fixing misbehaving buffers when using
@ref GL::Buffer::TargetHint::TransformFeedback. See @ref opengl-workarounds
for more information.
- New `--magnum-gpu-validation` @ref GL-Context-command-line "command-line option"
and a corresponding environment variable to conveniently enable
@gl_extension{KHR,debug} debug output

27
src/Magnum/GL/Buffer.cpp

@ -157,11 +157,17 @@ void Buffer::copy(Buffer& read, Buffer& write, const GLintptr readOffset, const
}
#endif
Buffer::Buffer(const TargetHint targetHint): _targetHint{targetHint}, _flags{ObjectFlag::DeleteOnDestruction} {
(this->*Context::current().state().buffer->createImplementation)();
Buffer::Buffer(const TargetHint targetHint): _flags{ObjectFlag::DeleteOnDestruction} {
Implementation::BufferState& state = *Context::current().state().buffer;
(this->*state.createImplementation)();
(this->*state.setTargetHintImplementation)(targetHint);
CORRADE_INTERNAL_ASSERT(_id != Implementation::State::DisengagedBinding);
}
Buffer::Buffer(GLuint id, TargetHint targetHint, ObjectFlags flags) noexcept: _id{id}, _flags{flags} {
(this->*Context::current().state().buffer->setTargetHintImplementation)(targetHint);
}
void Buffer::createImplementationDefault() {
glGenBuffers(1, &_id);
}
@ -186,6 +192,23 @@ Buffer::~Buffer() {
glDeleteBuffers(1, &_id);
}
Buffer& Buffer::setTargetHint(TargetHint hint) {
(this->*Context::current().state().buffer->setTargetHintImplementation)(hint);
return *this;
}
void Buffer::setTargetHintImplementationDefault(const TargetHint hint) {
_targetHint = hint;
}
#if defined(MAGNUM_TARGET_GLES) && !defined(MAGNUM_TARGET_GLES2)
void Buffer::setTargetHintImplementationSwiftShader(const TargetHint hint) {
/* See the "swiftshader-broken-xfb-buffer-binding-target" workaround for
details */
_targetHint = hint == TargetHint::TransformFeedback ? TargetHint::Array : hint;
}
#endif
inline void Buffer::createIfNotAlready() {
if(_flags & ObjectFlag::Created) return;

12
src/Magnum/GL/Buffer.h

@ -878,10 +878,7 @@ class MAGNUM_GL_EXPORT Buffer: public AbstractObject {
* to @fn_gl{BindBuffer}. Default target hint is @ref TargetHint::Array.
* @see @ref setData(), @ref setSubData()
*/
Buffer& setTargetHint(TargetHint hint) {
_targetHint = hint;
return *this;
}
Buffer& setTargetHint(TargetHint hint);
#ifndef MAGNUM_TARGET_GLES2
/**
@ -1251,13 +1248,18 @@ class MAGNUM_GL_EXPORT Buffer: public AbstractObject {
#endif
#endif
explicit Buffer(GLuint id, TargetHint targetHint, ObjectFlags flags) noexcept: _id{id}, _targetHint{targetHint}, _flags{flags} {}
explicit Buffer(GLuint id, TargetHint targetHint, ObjectFlags flags) noexcept;
void MAGNUM_GL_LOCAL createImplementationDefault();
#ifndef MAGNUM_TARGET_GLES
void MAGNUM_GL_LOCAL createImplementationDSA();
#endif
void MAGNUM_GL_LOCAL setTargetHintImplementationDefault(TargetHint hint);
#if defined(MAGNUM_TARGET_GLES) && !defined(MAGNUM_TARGET_GLES2)
void MAGNUM_GL_LOCAL setTargetHintImplementationSwiftShader(TargetHint hint);
#endif
void MAGNUM_GL_LOCAL createIfNotAlready();
#ifndef MAGNUM_TARGET_WEBGL

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

@ -182,6 +182,17 @@ BufferState::BufferState(Context& context, std::vector<std::string>& extensions)
}
#endif
#ifdef MAGNUM_TARGET_GLES
if((context.detectedDriver() & Context::DetectedDriver::SwiftShader) &&
!context.isDriverWorkaroundDisabled("swiftshader-broken-xfb-buffer-binding-target"))
{
setTargetHintImplementation = &Buffer::setTargetHintImplementationSwiftShader;
} else
#endif
{
setTargetHintImplementation = &Buffer::setTargetHintImplementationDefault;
}
#ifdef MAGNUM_TARGET_GLES
static_cast<void>(context);
static_cast<void>(extensions);

1
src/Magnum/GL/Implementation/BufferState.h

@ -54,6 +54,7 @@ struct BufferState {
void(*copyImplementation)(Buffer&, Buffer&, GLintptr, GLintptr, GLsizeiptr);
#endif
void(Buffer::*createImplementation)();
void(Buffer::*setTargetHintImplementation)(Buffer::TargetHint);
void(Buffer::*getParameterImplementation)(GLenum, GLint*);
#ifndef MAGNUM_TARGET_GLES2
void(Buffer::*getSubDataImplementation)(GLintptr, GLsizeiptr, GLvoid*);

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

@ -160,6 +160,16 @@ namespace {
"swiftshader-no-es2-oes-texture-3d-entrypoints",
#endif
#if defined(MAGNUM_TARGET_GLES) && !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
/* SwiftShader 4.1.0 has special handling for binding buffers to the
transform feedback target, requiring an XFB object to be active when
a buffer is bound to GL_TRANSFORM_FEEDBACK_BUFFER and ignoring the
glBindBuffer() call otherwise. No other driver does that. As a
workaround, setting Buffer::TargetHint::TransformFeedback will make
it use Buffer::TargetHint::Array instead, as that works okay. */
"swiftshader-broken-xfb-buffer-binding-target",
#endif
#ifndef MAGNUM_TARGET_GLES
/* Even with the DSA variant, where GL_IMPLEMENTATION_COLOR_READ_* is
passed to glGetNamedFramebufferParameter(), Mesa complains that the

Loading…
Cancel
Save