Browse Source

Added nv-windows-dangling-transform-feedback-varying-names workaround.

On Windows NVidia drivers the glTransformFeedbackVaryings() does not
make a copy of its char* arguments so it fails at link time when the
original char arrays are not in scope anymore. Enabling *synchronous*
debug output circumvents this bug. Can be triggered by running
TransformFeedbackGLTest with GL_KHR_debug extension disabled.
pull/179/head
Vladimír Vondruš 10 years ago
parent
commit
c93cc0ba08
  1. 17
      src/Magnum/AbstractShaderProgram.cpp
  2. 17
      src/Magnum/AbstractShaderProgram.h
  3. 13
      src/Magnum/Implementation/ShaderProgramState.cpp
  4. 9
      src/Magnum/Implementation/ShaderProgramState.h
  5. 8
      src/Magnum/Implementation/driverSpecific.cpp

17
src/Magnum/AbstractShaderProgram.cpp

@ -368,6 +368,10 @@ void AbstractShaderProgram::bindFragmentDataLocationIndexedInternal(const Unsign
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
void AbstractShaderProgram::setTransformFeedbackOutputs(const std::initializer_list<std::string> outputs, const TransformFeedbackBufferMode bufferMode) { void AbstractShaderProgram::setTransformFeedbackOutputs(const std::initializer_list<std::string> outputs, const TransformFeedbackBufferMode bufferMode) {
(this->*Context::current().state().shaderProgram->transformFeedbackVaryingsImplementation)({outputs.begin(), outputs.size()}, bufferMode);
}
void AbstractShaderProgram::transformFeedbackVaryingsImplementationDefault(const Containers::ArrayView<const std::string> outputs, const TransformFeedbackBufferMode bufferMode) {
/** @todo VLAs */ /** @todo VLAs */
Containers::Array<const char*> names{outputs.size()}; Containers::Array<const char*> names{outputs.size()};
@ -376,6 +380,19 @@ void AbstractShaderProgram::setTransformFeedbackOutputs(const std::initializer_l
glTransformFeedbackVaryings(_id, outputs.size(), names, GLenum(bufferMode)); glTransformFeedbackVaryings(_id, outputs.size(), names, GLenum(bufferMode));
} }
#ifdef CORRADE_TARGET_WINDOWS
void AbstractShaderProgram::transformFeedbackVaryingsImplementationDanglingWorkaround(const Containers::ArrayView<const std::string> outputs, const TransformFeedbackBufferMode bufferMode) {
/* NVidia on Windows doesn't copy the names when calling
glTransformFeedbackVaryings() so it then fails at link time because the
char* are dangling. We have to do the copy on the engine side and keep
the values until link time (which can happen any time and multiple
times, so basically for the remaining lifetime of the shader program) */
_transformFeedbackVaryingNames.assign(outputs.begin(), outputs.end());
transformFeedbackVaryingsImplementationDefault({_transformFeedbackVaryingNames.data(), _transformFeedbackVaryingNames.size()}, bufferMode);
}
#endif
#endif #endif
bool AbstractShaderProgram::link(std::initializer_list<std::reference_wrapper<AbstractShaderProgram>> shaders) { bool AbstractShaderProgram::link(std::initializer_list<std::reference_wrapper<AbstractShaderProgram>> shaders) {

17
src/Magnum/AbstractShaderProgram.h

@ -36,6 +36,10 @@
#include "Magnum/AbstractObject.h" #include "Magnum/AbstractObject.h"
#include "Magnum/Attribute.h" #include "Magnum/Attribute.h"
#if defined(CORRADE_TARGET_WINDOWS) && !defined(MAGNUM_TARGET_GLES2)
#include <vector>
#endif
namespace Magnum { namespace Magnum {
namespace Implementation { struct ShaderProgramState; } namespace Implementation { struct ShaderProgramState; }
@ -1189,6 +1193,13 @@ class MAGNUM_EXPORT AbstractShaderProgram: public AbstractObject {
Int uniformLocationInternal(Containers::ArrayView<const char> name); Int uniformLocationInternal(Containers::ArrayView<const char> name);
UnsignedInt uniformBlockIndexInternal(Containers::ArrayView<const char> name); UnsignedInt uniformBlockIndexInternal(Containers::ArrayView<const char> name);
#ifndef MAGNUM_TARGET_GLES2
void MAGNUM_LOCAL transformFeedbackVaryingsImplementationDefault(Containers::ArrayView<const std::string> outputs, TransformFeedbackBufferMode bufferMode);
#ifdef CORRADE_TARGET_WINDOWS
void MAGNUM_LOCAL transformFeedbackVaryingsImplementationDanglingWorkaround(Containers::ArrayView<const std::string> outputs, TransformFeedbackBufferMode bufferMode);
#endif
#endif
#ifndef MAGNUM_BUILD_DEPRECATED #ifndef MAGNUM_BUILD_DEPRECATED
void use(); void use();
#endif #endif
@ -1347,6 +1358,12 @@ class MAGNUM_EXPORT AbstractShaderProgram: public AbstractObject {
#endif #endif
GLuint _id; GLuint _id;
#if defined(CORRADE_TARGET_WINDOWS) && !defined(MAGNUM_TARGET_GLES2)
/* Needed for the nv-windows-dangling-transform-feedback-varying-names
workaround */
std::vector<std::string> _transformFeedbackVaryingNames;
#endif
}; };
} }

13
src/Magnum/Implementation/ShaderProgramState.cpp

@ -47,6 +47,19 @@ ShaderProgramState::ShaderProgramState(Context& context, std::vector<std::string
, maxImageSamples(0) , maxImageSamples(0)
#endif #endif
{ {
#ifndef MAGNUM_TARGET_GLES2
#ifdef CORRADE_TARGET_WINDOWS
if((context.detectedDriver() & Context::DetectedDriver::NVidia) &&
!context.isDriverWorkaroundDisabled("nv-windows-dangling-transform-feedback-varying-names"))
{
transformFeedbackVaryingsImplementation = &AbstractShaderProgram::transformFeedbackVaryingsImplementationDanglingWorkaround;
} else
#endif
{
transformFeedbackVaryingsImplementation = &AbstractShaderProgram::transformFeedbackVaryingsImplementationDefault;
}
#endif
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(context.isExtensionSupported<Extensions::GL::ARB::separate_shader_objects>()) if(context.isExtensionSupported<Extensions::GL::ARB::separate_shader_objects>())

9
src/Magnum/Implementation/ShaderProgramState.h

@ -32,10 +32,7 @@
#include "Magnum/OpenGL.h" #include "Magnum/OpenGL.h"
#include "Magnum/Math/Vector3.h" #include "Magnum/Math/Vector3.h"
#ifdef _MSC_VER #ifndef MAGNUM_TARGET_GLES2
/* Otherwise the member function pointers will have different size based on
whether the header was included or not. CAUSES SERIOUS MEMORY CORRUPTION AND
IS NOT CAUGHT BY ANY WARNING WHATSOEVER! AARGH! */
#include "Magnum/AbstractShaderProgram.h" #include "Magnum/AbstractShaderProgram.h"
#endif #endif
@ -46,6 +43,10 @@ struct ShaderProgramState {
void reset(); void reset();
#ifndef MAGNUM_TARGET_GLES2
void(AbstractShaderProgram::*transformFeedbackVaryingsImplementation)(Containers::ArrayView<const std::string>, AbstractShaderProgram::TransformFeedbackBufferMode);
#endif
void(AbstractShaderProgram::*uniform1fvImplementation)(GLint, GLsizei, const GLfloat*); void(AbstractShaderProgram::*uniform1fvImplementation)(GLint, GLsizei, const GLfloat*);
void(AbstractShaderProgram::*uniform2fvImplementation)(GLint, GLsizei, const Math::Vector<2, GLfloat>*); void(AbstractShaderProgram::*uniform2fvImplementation)(GLint, GLsizei, const Math::Vector<2, GLfloat>*);
void(AbstractShaderProgram::*uniform3fvImplementation)(GLint, GLsizei, const Math::Vector<3, GLfloat>*); void(AbstractShaderProgram::*uniform3fvImplementation)(GLint, GLsizei, const Math::Vector<3, GLfloat>*);

8
src/Magnum/Implementation/driverSpecific.cpp

@ -48,6 +48,14 @@ namespace {
GLSL even though the extension (e.g. binding keyword) is not GLSL even though the extension (e.g. binding keyword) is not
supported */ supported */
"intel-windows-glsl-exposes-unsupported-shading-language-420pack", "intel-windows-glsl-exposes-unsupported-shading-language-420pack",
/* On Windows NVidia drivers the glTransformFeedbackVaryings() does not
make a copy of its char* arguments so it fails at link time when the
original char arrays are not in scope anymore. Enabling
*synchronous* debug output circumvents this bug. Can be triggered by
running TransformFeedbackGLTest with GL_KHR_debug extension
disabled. */
"nv-windows-dangling-transform-feedback-varying-names",
#endif #endif
/* Layout qualifier causes compiler error with GLSL 1.20 on Mesa, GLSL /* Layout qualifier causes compiler error with GLSL 1.20 on Mesa, GLSL

Loading…
Cancel
Save