Skip to content

Commit 31a72fd

Browse files
GLSL Utils: added GetGLSLExtensions function
1 parent 9250ff8 commit 31a72fd

File tree

4 files changed

+154
-0
lines changed

4 files changed

+154
-0
lines changed

Graphics/ShaderTools/include/GLSLUtils.hpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@
2727

2828
#pragma once
2929

30+
#include <vector>
31+
#include <string>
32+
#include <utility>
33+
3034
#include "BasicTypes.h"
3135
#include "GraphicsTypes.h"
3236
#include "Shader.h"
@@ -73,4 +77,8 @@ void GetGLSLVersion(const ShaderCreateInfo& ShaderCI,
7377
ShaderVersion& GLSLVer,
7478
bool& IsES);
7579

80+
/// Extracts all #extension directives from the GLSL source, returning them as a vector of pairs
81+
/// (extension name, extension behavior). The behavior is the string following the extension name.
82+
std::vector<std::pair<std::string, std::string>> GetGLSLExtensions(const char* Source, size_t SourceLen = 0);
83+
7684
} // namespace Diligent

Graphics/ShaderTools/src/GLSLUtils.cpp

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
#include "RefCntAutoPtr.hpp"
3737
#include "DataBlobImpl.hpp"
3838
#include "ShaderToolsCommon.hpp"
39+
#include "ParsingTools.hpp"
3940

4041
namespace Diligent
4142
{
@@ -403,4 +404,79 @@ String BuildGLSLSourceString(const BuildGLSLSourceStringAttribs& Attribs) noexce
403404
return GLSLSource;
404405
}
405406

407+
std::vector<std::pair<std::string, std::string>> GetGLSLExtensions(const char* Source, size_t SourceLen)
408+
{
409+
if (Source == nullptr)
410+
return {};
411+
412+
if (SourceLen == 0)
413+
SourceLen = std::strlen(Source);
414+
415+
std::vector<std::pair<std::string, std::string>> Extensions;
416+
417+
const auto* Pos = Source;
418+
const auto* const End = Source + SourceLen;
419+
while (Pos != End)
420+
{
421+
const char *NameStart = nullptr, *NameEnd = nullptr;
422+
Pos = Parsing::FindNextPreprocessorDirective(Pos, End, NameStart, NameEnd);
423+
if (Pos == End)
424+
break;
425+
426+
VERIFY_EXPR(*Pos == '#');
427+
428+
// # extension GL_ARB_shader_draw_parameters : enable
429+
// ^ ^ ^
430+
// | | NameEnd
431+
// | NameStart
432+
// Pos
433+
434+
const auto* LineEnd = Parsing::SkipLine(NameEnd, End, /* GoToNextLine = */ false);
435+
436+
std::string DirectiveIdentifier{NameStart, NameEnd};
437+
if (DirectiveIdentifier == "extension")
438+
{
439+
const auto* ExtNameStart = Parsing::SkipDelimiters(NameEnd, LineEnd, " \t");
440+
// # extension GL_ARB_shader_draw_parameters : enable
441+
// ^
442+
// ExtNameStart
443+
444+
const auto* ExtNameEnd = Parsing::SkipIdentifier(ExtNameStart, LineEnd);
445+
// # extension GL_ARB_shader_draw_parameters : enable
446+
// ^
447+
// ExtNameStart
448+
449+
std::string ExtensionName{ExtNameStart, ExtNameEnd};
450+
if (!ExtensionName.empty())
451+
{
452+
Pos = ExtNameEnd;
453+
while (Pos != LineEnd && *Pos != ':')
454+
++Pos;
455+
456+
std::string ExtensionBehavior;
457+
if (Pos != LineEnd && *Pos == ':')
458+
{
459+
const auto* BehaviorStart = Parsing::SkipDelimiters(Pos + 1, LineEnd, " \t");
460+
// # extension GL_ARB_shader_draw_parameters : enable
461+
// ^
462+
// BehaviorStart
463+
464+
const auto* BehaviorEnd = Parsing::SkipIdentifier(BehaviorStart, LineEnd);
465+
// # extension GL_ARB_shader_draw_parameters : enable
466+
// ^
467+
// BehaviorEnd
468+
469+
ExtensionBehavior.assign(BehaviorStart, BehaviorEnd);
470+
}
471+
472+
Extensions.emplace_back(std::move(ExtensionName), std::move(ExtensionBehavior));
473+
}
474+
}
475+
476+
Pos = Parsing::SkipLine(LineEnd, End, /* GoToNextLine = */ true);
477+
}
478+
479+
return Extensions;
480+
}
481+
406482
} // namespace Diligent

Tests/DiligentCoreTest/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ project(DiligentCoreTest)
99
file(GLOB_RECURSE SOURCE src/*.*)
1010
file(GLOB_RECURSE SHADERS assets/shaders/*.*)
1111

12+
if(NOT GL_SUPPORTED AND NOT GLES_SUPPORTED AND NOT VULKAN_SUPPORTED)
13+
list(REMOVE_ITEM SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/src/ShaderTools/GLSLUtilsTest.cpp)
14+
endif()
15+
1216
set_source_files_properties(${SHADERS} PROPERTIES VS_TOOL_OVERRIDE "None")
1317

1418
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/*
2+
* Copyright 2024 Diligent Graphics LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*
16+
* In no event and under no legal theory, whether in tort (including negligence),
17+
* contract, or otherwise, unless required by applicable law (such as deliberate
18+
* and grossly negligent acts) or agreed to in writing, shall any Contributor be
19+
* liable for any damages, including any direct, indirect, special, incidental,
20+
* or consequential damages of any character arising as a result of this License or
21+
* out of the use or inability to use the software (including but not limited to damages
22+
* for loss of goodwill, work stoppage, computer failure or malfunction, or any and
23+
* all other commercial damages or losses), even if such Contributor has been advised
24+
* of the possibility of such damages.
25+
*/
26+
27+
#include "GLSLUtils.hpp"
28+
29+
#include "TestingEnvironment.hpp"
30+
#include "gtest/gtest.h"
31+
32+
using namespace Diligent;
33+
using namespace Diligent::Testing;
34+
35+
namespace
36+
{
37+
38+
TEST(GLSLUtilsTest, GetGLSLExtensions)
39+
{
40+
auto Test = [](const std::string& Source, const std::vector<std::pair<std::string, std::string>>& RefExtensions) {
41+
auto Extensions = GetGLSLExtensions(Source.c_str(), Source.length());
42+
EXPECT_EQ(Extensions.size(), RefExtensions.size());
43+
44+
for (size_t i = 0; i < std::min(Extensions.size(), RefExtensions.size()); ++i)
45+
{
46+
EXPECT_EQ(Extensions[i].first, RefExtensions[i].first);
47+
EXPECT_EQ(Extensions[i].second, RefExtensions[i].second);
48+
}
49+
};
50+
51+
Test("", {});
52+
Test("#", {});
53+
Test("# define", {});
54+
Test("# extension", {});
55+
Test("# extension ABC", {{"ABC", ""}});
56+
Test("# extension : enable", {});
57+
Test("# extension ABC : enable", {{"ABC", "enable"}});
58+
59+
Test(R"(
60+
# extension ABC : enable
61+
# extension XYZ : require
62+
)",
63+
{{"ABC", "enable"}, {"XYZ", "require"}});
64+
}
65+
66+
} // namespace

0 commit comments

Comments
 (0)