29
29
30
30
#include < Corrade/Containers/Array.h>
31
31
#include < Corrade/Containers/Iterable.h>
32
- #include < Corrade/Containers/StridedArrayView.h>
33
- #ifndef MAGNUM_TARGET_WEBGL
34
- #include < Corrade/Containers/String.h>
35
- #endif
36
- #include < Corrade/Containers/StringStl.h> /* * @todo remove once <string>-free */
37
32
#ifdef MAGNUM_BUILD_DEPRECATED
38
33
#include < Corrade/Containers/Reference.h>
39
34
#endif
40
- #include < Corrade/Utility/DebugStl.h>
41
- #include < Corrade/Utility/String.h>
35
+ #include < Corrade/Containers/StridedArrayView.h>
36
+ #include < Corrade/Containers/String.h>
37
+ #include < Corrade/Containers/StringIterable.h>
42
38
43
39
#include " Magnum/GL/Context.h"
44
40
#include " Magnum/GL/Extensions.h"
@@ -343,26 +339,29 @@ AbstractShaderProgram& AbstractShaderProgram::setLabel(const Containers::StringV
343
339
}
344
340
#endif
345
341
346
- std::pair<bool , std::string > AbstractShaderProgram::validate () {
342
+ std::pair<bool , Containers::String > AbstractShaderProgram::validate () {
347
343
glValidateProgram (_id);
348
344
349
345
/* Check validation status */
350
346
GLint success, logLength;
351
347
glGetProgramiv (_id, GL_VALIDATE_STATUS, &success);
352
348
glGetProgramiv (_id, GL_INFO_LOG_LENGTH, &logLength);
353
349
354
- /* Error or warning message. The string is returned null-terminated, scrap
355
- the \0 at the end afterwards */
356
- std::string message (logLength, ' \n ' );
357
- if ( message. size () > 1 )
358
- glGetProgramInfoLog (_id, message. size (), nullptr , &message[ 0 ]);
359
- message. resize ( Math::max ( logLength, 1 )- 1 );
350
+ /* Error or warning message. The length is reported including the null
351
+ terminator and the string implicitly has a storage for that, thus
352
+ specify one byte less. */
353
+ Containers::String message{NoInit, std::size_t ( Math::max (logLength, 1 ) - 1 )};
354
+ if (logLength > 1 )
355
+ glGetProgramInfoLog (_id, logLength, nullptr , message. data () );
360
356
361
357
/* On some drivers (such as SwiftShader) the message contains a newline at
362
358
the end, on some (such as Mesa) it doesn't. Same as with link() or
363
359
compile() message trimming it doesn't make sense to add driver-specific
364
360
workarounds for this, so just trim it always. */
365
- return {success, Utility::String::trim (std::move (message))};
361
+ /* * @todo this allocates a new string, revisit once String is capable of
362
+ trimming in-place, e.g. `std::move(message).trimmed()` would just
363
+ shift the data around */
364
+ return {success, message.trimmed ()};
366
365
}
367
366
368
367
AbstractShaderProgram& AbstractShaderProgram::draw (Mesh& mesh) {
@@ -547,48 +546,62 @@ void AbstractShaderProgram::attachShaders(const Containers::Iterable<Shader>& sh
547
546
for (Shader& s: shaders) attachShader (s);
548
547
}
549
548
550
- void AbstractShaderProgram::bindAttributeLocationInternal (const UnsignedInt location, const Containers::ArrayView< const char > name) {
551
- glBindAttribLocation (_id, location, name);
549
+ void AbstractShaderProgram::bindAttributeLocation (const UnsignedInt location, const Containers::StringView name) {
550
+ glBindAttribLocation (_id, location, Containers::String::nullTerminatedView ( name). data () );
552
551
}
553
552
554
553
#ifndef MAGNUM_TARGET_GLES
555
- void AbstractShaderProgram::bindFragmentDataLocationInternal (const UnsignedInt location, const Containers::ArrayView< const char > name) {
556
- glBindFragDataLocation (_id, location, name);
554
+ void AbstractShaderProgram::bindFragmentDataLocation (const UnsignedInt location, const Containers::StringView name) {
555
+ glBindFragDataLocation (_id, location, Containers::String::nullTerminatedView ( name). data () );
557
556
}
558
- void AbstractShaderProgram::bindFragmentDataLocationIndexedInternal (const UnsignedInt location, UnsignedInt index, const Containers::ArrayView< const char > name) {
559
- glBindFragDataLocationIndexed (_id, location, index , name);
557
+ void AbstractShaderProgram::bindFragmentDataLocationIndexed (const UnsignedInt location, UnsignedInt index, const Containers::StringView name) {
558
+ glBindFragDataLocationIndexed (_id, location, index , Containers::String::nullTerminatedView ( name). data () );
560
559
}
561
560
#endif
562
561
563
562
#ifndef MAGNUM_TARGET_GLES2
564
- void AbstractShaderProgram::setTransformFeedbackOutputs (const Containers::ArrayView< const std::string> outputs, const TransformFeedbackBufferMode bufferMode) {
563
+ void AbstractShaderProgram::setTransformFeedbackOutputs (const Containers::StringIterable& outputs, const TransformFeedbackBufferMode bufferMode) {
565
564
(this ->*Context::current ().state ().shaderProgram .transformFeedbackVaryingsImplementation )(outputs, bufferMode);
566
565
}
567
566
568
- void AbstractShaderProgram::setTransformFeedbackOutputs (const std::initializer_list<std::string> outputs, const TransformFeedbackBufferMode bufferMode) {
569
- setTransformFeedbackOutputs (Containers::arrayView (outputs), bufferMode);
570
- }
571
-
572
- void AbstractShaderProgram::transformFeedbackVaryingsImplementationDefault (const Containers::ArrayView<const std::string> outputs, const TransformFeedbackBufferMode bufferMode) {
573
- /* * @todo VLAs */
574
- Containers::Array<const char *> names{outputs.size ()};
575
-
576
- Int i = 0 ;
577
- for (const std::string& output: outputs) names[i++] = output.data ();
567
+ void AbstractShaderProgram::transformFeedbackVaryingsImplementationDefault (const Containers::StringIterable& outputs, const TransformFeedbackBufferMode bufferMode) {
568
+ Containers::ArrayView<Containers::String> nameData;
569
+ Containers::ArrayView<const char *> names;
570
+ Containers::ArrayTuple data{
571
+ {NoInit, outputs.size (), nameData},
572
+ {NoInit, outputs.size (), names}
573
+ };
574
+ for (std::size_t i = 0 ; i != outputs.size (); ++i) {
575
+ new (&nameData[i]) Containers::String{Containers::String::nullTerminatedView (outputs[i])};
576
+ names[i] = nameData[i].data ();
577
+ }
578
578
579
579
glTransformFeedbackVaryings (_id, outputs.size (), names, GLenum (bufferMode));
580
580
}
581
581
582
582
#ifdef CORRADE_TARGET_WINDOWS
583
- void AbstractShaderProgram::transformFeedbackVaryingsImplementationDanglingWorkaround (const Containers::ArrayView< const std::string> outputs, const TransformFeedbackBufferMode bufferMode) {
583
+ void AbstractShaderProgram::transformFeedbackVaryingsImplementationDanglingWorkaround (const Containers::StringIterable& outputs, const TransformFeedbackBufferMode bufferMode) {
584
584
/* NVidia on Windows doesn't copy the names when calling
585
- glTransformFeedbackVaryings() so it then fails at link time because the
586
- char* are dangling. We have to do the copy on the engine side and keep
587
- the values until link time (which can happen any time and multiple
588
- times, so basically for the remaining lifetime of the shader program) */
589
- _transformFeedbackVaryingNames.assign (outputs.begin (), outputs.end ());
585
+ glTransformFeedbackVaryings() so it then might fail at link time because
586
+ the char* get dangling. We have to do the copy on the engine side and
587
+ keep the values until link time (which can happen any time and multiple
588
+ times, so basically for the remaining lifetime of the shader program).
589
+
590
+ Compared to the above case we thus do a copy also if the view is not
591
+ global in addition to not null-terminated, and we keep the string memory
592
+ in a member variable. */
593
+ Containers::ArrayView<Containers::String> nameData;
594
+ Containers::ArrayView<const char *> names;
595
+ _transformFeedbackVaryingNames = Containers::ArrayTuple{
596
+ {NoInit, outputs.size (), nameData},
597
+ {NoInit, outputs.size (), names}
598
+ };
599
+ for (std::size_t i = 0 ; i != outputs.size (); ++i) {
600
+ new (&nameData[i]) Containers::String{Containers::String::nullTerminatedGlobalView (outputs[i])};
601
+ names[i] = nameData[i].data ();
602
+ }
590
603
591
- transformFeedbackVaryingsImplementationDefault ({_transformFeedbackVaryingNames. data (), _transformFeedbackVaryingNames .size ()}, bufferMode);
604
+ glTransformFeedbackVaryings (_id, outputs .size (), names, GLenum ( bufferMode) );
592
605
}
593
606
#endif
594
607
#endif
@@ -613,12 +626,12 @@ bool AbstractShaderProgram::checkLink(const Containers::Iterable<Shader>& shader
613
626
glGetProgramiv (_id, GL_LINK_STATUS, &success);
614
627
glGetProgramiv (_id, GL_INFO_LOG_LENGTH, &logLength);
615
628
616
- /* Error or warning message. The string is returned null-terminated,
617
- strip the \0 at the end afterwards. */
618
- std::string message (logLength, ' \n ' );
619
- if ( message. size () > 1 )
620
- glGetProgramInfoLog (_id, message. size (), nullptr , &message[ 0 ]);
621
- message. resize ( Math::max ( logLength, 1 )- 1 );
629
+ /* Error or warning message. The length is reported including the null
630
+ terminator and the string implicitly has a storage for that, thus
631
+ specify one byte less. */
632
+ Containers::String message{NoInit, std::size_t ( Math::max (logLength, 1 )) - 1 };
633
+ if (logLength > 1 )
634
+ glGetProgramInfoLog (_id, logLength, nullptr , message. data () );
622
635
623
636
/* Some drivers are chatty and can't keep shut when there's nothing to
624
637
be said, handle that as well. */
@@ -662,16 +675,16 @@ bool AbstractShaderProgram::isLinkFinished() {
662
675
return success == GL_TRUE;
663
676
}
664
677
665
- void AbstractShaderProgram::cleanLogImplementationNoOp (std::string &) {}
678
+ void AbstractShaderProgram::cleanLogImplementationNoOp (Containers::String &) {}
666
679
667
680
#if defined(CORRADE_TARGET_WINDOWS) && !defined(MAGNUM_TARGET_GLES)
668
- void AbstractShaderProgram::cleanLogImplementationIntelWindows (std::string & message) {
681
+ void AbstractShaderProgram::cleanLogImplementationIntelWindows (Containers::String & message) {
669
682
if (message == " No errors.\n " ) message = {};
670
683
}
671
684
#endif
672
685
673
686
#if defined(MAGNUM_TARGET_GLES) && !defined(MAGNUM_TARGET_WEBGL)
674
- void AbstractShaderProgram::cleanLogImplementationAngle (std::string & message) {
687
+ void AbstractShaderProgram::cleanLogImplementationAngle (Containers::String & message) {
675
688
if (message == " \n " ) message = {};
676
689
}
677
690
#endif
@@ -680,18 +693,18 @@ void AbstractShaderProgram::completionStatusImplementationFallback(GLuint, GLenu
680
693
*value = GL_TRUE;
681
694
}
682
695
683
- Int AbstractShaderProgram::uniformLocationInternal (const Containers::ArrayView< const char > name) {
684
- const GLint location = glGetUniformLocation (_id, name);
696
+ Int AbstractShaderProgram::uniformLocation (const Containers::StringView name) {
697
+ const GLint location = glGetUniformLocation (_id, Containers::String::nullTerminatedView ( name). data () );
685
698
if (location == -1 )
686
- Warning{} << " GL::AbstractShaderProgram: location of uniform \' " << Debug::nospace << std::string{ name, name. size ()} << Debug::nospace << " \' cannot be retrieved" ;
699
+ Warning{} << " GL::AbstractShaderProgram: location of uniform \' " << Debug::nospace << name << Debug::nospace << " \' cannot be retrieved" ;
687
700
return location;
688
701
}
689
702
690
703
#ifndef MAGNUM_TARGET_GLES2
691
- UnsignedInt AbstractShaderProgram::uniformBlockIndexInternal (const Containers::ArrayView< const char > name) {
692
- const GLuint index = glGetUniformBlockIndex (_id, name);
704
+ UnsignedInt AbstractShaderProgram::uniformBlockIndex (const Containers::StringView name) {
705
+ const GLuint index = glGetUniformBlockIndex (_id, Containers::String::nullTerminatedView ( name). data () );
693
706
if (index == GL_INVALID_INDEX)
694
- Warning{} << " GL::AbstractShaderProgram: index of uniform block \' " << Debug::nospace << std::string{ name, name. size ()} << Debug::nospace << " \' cannot be retrieved" ;
707
+ Warning{} << " GL::AbstractShaderProgram: index of uniform block \' " << Debug::nospace << name << Debug::nospace << " \' cannot be retrieved" ;
695
708
return index ;
696
709
}
697
710
#endif
0 commit comments