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
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 */
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));
}
#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
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/Attribute.h"
#if defined(CORRADE_TARGET_WINDOWS) && !defined(MAGNUM_TARGET_GLES2)
#include <vector>
#endif
namespace Magnum {
namespace Implementation { struct ShaderProgramState; }
@ -1189,6 +1193,13 @@ class MAGNUM_EXPORT AbstractShaderProgram: public AbstractObject {
Int uniformLocationInternal(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
void use();
#endif
@ -1347,6 +1358,12 @@ class MAGNUM_EXPORT AbstractShaderProgram: public AbstractObject {
#endif
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)
#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)
#ifndef MAGNUM_TARGET_GLES
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/Math/Vector3.h"
#ifdef _MSC_VER
/* 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! */
#ifndef MAGNUM_TARGET_GLES2
#include "Magnum/AbstractShaderProgram.h"
#endif
@ -46,6 +43,10 @@ struct ShaderProgramState {
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::*uniform2fvImplementation)(GLint, GLsizei, const Math::Vector<2, 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
supported */
"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
/* Layout qualifier causes compiler error with GLSL 1.20 on Mesa, GLSL

Loading…
Cancel
Save