Skip to content

Commit

Permalink
Add glslang::Backend to break cyclic dependency
Browse files Browse the repository at this point in the history
between `HLSL` and `glslang` build targets.

Applications now require a call to `glslang::RegisterHLSLBackend()`
to enable the HLSL backend. This is implemented in the HLSL library.

Fixes building of shared libraries.
  • Loading branch information
ben-clayton committed Jun 10, 2020
1 parent 45de441 commit e13b079
Show file tree
Hide file tree
Showing 11 changed files with 330 additions and 44 deletions.
2 changes: 2 additions & 0 deletions Android.mk
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ LOCAL_MODULE:=HLSL
LOCAL_CXXFLAGS:=-std=c++11 -fno-exceptions -fno-rtti $(GLSLANG_DEFINES)
LOCAL_SRC_FILES:= \
hlsl/hlslAttributes.cpp \
hlsl/hlslBackend.cpp \
hlsl/hlslGrammar.cpp \
hlsl/hlslOpMap.cpp \
hlsl/hlslParseables.cpp \
Expand All @@ -49,6 +50,7 @@ LOCAL_SRC_FILES:= \
glslang/GenericCodeGen/Link.cpp \
glslang/MachineIndependent/attribute.cpp \
glslang/MachineIndependent/Constant.cpp \
glslang/MachineIndependent/Backend.cpp \
glslang/MachineIndependent/glslang_tab.cpp \
glslang/MachineIndependent/InfoSink.cpp \
glslang/MachineIndependent/Initialize.cpp \
Expand Down
2 changes: 2 additions & 0 deletions BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ source_set("glslang_sources") {
"glslang/Include/arrays.h",
"glslang/Include/intermediate.h",
"glslang/Include/revision.h",
"glslang/MachineIndependent/Backend.cpp",
"glslang/MachineIndependent/Constant.cpp",
"glslang/MachineIndependent/InfoSink.cpp",
"glslang/MachineIndependent/Initialize.cpp",
Expand Down Expand Up @@ -149,6 +150,7 @@ source_set("glslang_sources") {
"glslang/Public/ShaderLang.h",
"hlsl/hlslAttributes.cpp",
"hlsl/hlslAttributes.h",
"hlsl/hlslBackend.cpp",
"hlsl/hlslGrammar.cpp",
"hlsl/hlslGrammar.h",
"hlsl/hlslOpMap.cpp",
Expand Down
4 changes: 4 additions & 0 deletions StandAlone/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ set(LIBRARIES
SPIRV
glslang-default-resource-limits)

if(ENABLE_HLSL)
set(LIBRARIES ${LIBRARIES} HLSL)
endif()

if(ENABLE_SPVREMAPPER)
set(LIBRARIES ${LIBRARIES} SPVRemapper)
endif()
Expand Down
4 changes: 4 additions & 0 deletions StandAlone/StandAlone.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1250,6 +1250,10 @@ void CompileAndLinkShaderFiles(glslang::TWorklist& Worklist)

int singleMain()
{
#ifdef ENABLE_HLSL
glslang::RegisterHLSLBackend();
#endif

glslang::TWorklist workList;
std::for_each(WorkItems.begin(), WorkItems.end(), [&workList](std::unique_ptr<glslang::TWorkItem>& item) {
assert(item);
Expand Down
7 changes: 2 additions & 5 deletions glslang/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ set(SOURCES
MachineIndependent/glslang.y
MachineIndependent/glslang_tab.cpp
MachineIndependent/attribute.cpp
MachineIndependent/Backend.cpp
MachineIndependent/Constant.cpp
MachineIndependent/iomapper.cpp
MachineIndependent/InfoSink.cpp
Expand Down Expand Up @@ -86,18 +87,14 @@ add_library(glslang ${LIB_TYPE} ${BISON_GLSLParser_OUTPUT_SOURCE} ${SOURCES} ${H
set_property(TARGET glslang PROPERTY FOLDER glslang)
set_property(TARGET glslang PROPERTY POSITION_INDEPENDENT_CODE ON)
target_link_libraries(glslang OGLCompiler OSDependent)
target_include_directories(glslang PUBLIC
target_include_directories(glslang PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/..>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)

if(WIN32 AND BUILD_SHARED_LIBS)
set_target_properties(glslang PROPERTIES PREFIX "")
endif()

if(ENABLE_HLSL)
target_link_libraries(glslang HLSL)
endif()

if(WIN32)
source_group("Public" REGULAR_EXPRESSION "Public/*")
source_group("MachineIndependent" REGULAR_EXPRESSION "MachineIndependent/[^/]*")
Expand Down
117 changes: 117 additions & 0 deletions glslang/MachineIndependent/Backend.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
//
// Copyright (C) 2020 Google, Inc.
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
//
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//

#include "Backend.h"
#include "ParseHelper.h"
#include "ScanContext.h"

#include <array>

namespace glslang {

namespace {

class GlslBackend : public Backend {
public:
static GlslBackend instance;

void Initialize() override {
TScanContext::fillInKeywordMap();
}

void Terminate() override {
TScanContext::deleteKeywordMap();
}

EShSource Source() const override {
return EShSourceGlsl;
}

TBuiltInParseables* CreateBuiltInParseables(TInfoSink&) override {
return new TBuiltIns();
}

TParseContextBase* CreateParseContext(TSymbolTable& symbolTable, TIntermediate& intermediate,
int version, EProfile profile,
EShLanguage language, TInfoSink& infoSink,
SpvVersion spvVersion, bool forwardCompatible, EShMessages messages,
bool parsingBuiltIns, std::string sourceEntryPointName) override {
if (sourceEntryPointName.size() == 0)
intermediate.setEntryPointName("main");
TString entryPoint = sourceEntryPointName.c_str();
return new TParseContext(symbolTable, intermediate, parsingBuiltIns, version, profile, spvVersion,
language, infoSink, forwardCompatible, messages, &entryPoint);
}
};

GlslBackend GlslBackend::instance;

std::array<Backend*, EShSourceCount> backends = {};

// Automatically register the GLSL backend when the static initializers are run
// for this compilation unit.
struct AutoRegisterGlslBackend {
AutoRegisterGlslBackend() { Backend::Register(&GlslBackend::instance); }
} autoRegisterGlslBackend;

} // end anonymous namespace

void Backend::InitializeAll() {
for (Backend* backend : backends) {
if (backend) {
backend->Initialize();
}
}
}

void Backend::TerminateAll() {
for (Backend* backend : backends) {
if (backend) {
backend->Terminate();
}
}
}

void Backend::Register(Backend* backend) {
EShSource source = backend->Source();
backends[source] = backend;
}

Backend* Backend::Get(EShSource source) {
return backends[source];
}

} // end namespace glslang

89 changes: 89 additions & 0 deletions glslang/MachineIndependent/Backend.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
//
// Copyright (C) 2020 Google, Inc.
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
//
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
#ifndef _GLSLANG_BACKEND_INCLUDED_
#define _GLSLANG_BACKEND_INCLUDED_

#include "Initialize.h"

namespace glslang {

class TParseContextBase;

// Backend is an interface implemented by a language backend.
// Backends are registered by source (EShSource).
class Backend {
public:
virtual ~Backend() {}

// Register() registers the backend.
static void Register(Backend*);

// Get() returns the registered backend for the given source type.
static Backend* Get(EShSource source);

// InitializeAll() initializes all the registered backends.
static void InitializeAll();

// TerminateAll() terminates all the registered backends.
static void TerminateAll();

// Initialize() initializes the backend.
// Must be called, once, before any other method (with exception to Source()).
virtual void Initialize() = 0;

// Terminate() terminates the backend.
// Must be called, once, before process termination.
// No method may be called after calling.
virtual void Terminate() = 0;

// Source() returns the EShSource that this backend implements.
virtual EShSource Source() const = 0;

// CreateBuiltInParseables() constructs and returns the parseable strings
// for the given backend.
virtual TBuiltInParseables* CreateBuiltInParseables(TInfoSink& infoSink) = 0;

// CreateParseContext() constructs and returns the parse context for the
// given backend.
virtual TParseContextBase* CreateParseContext(TSymbolTable& symbolTable, TIntermediate& intermediate,
int version, EProfile profile,
EShLanguage language, TInfoSink& infoSink,
SpvVersion spvVersion, bool forwardCompatible, EShMessages messages,
bool parsingBuiltIns, std::string sourceEntryPointName) = 0;
};

} // end namespace glslang

#endif // _GLSLANG_BACKEND_INCLUDED_
53 changes: 14 additions & 39 deletions glslang/MachineIndependent/ShaderLang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,17 +45,12 @@
#include <iostream>
#include <sstream>
#include <memory>
#include "Backend.h"
#include "SymbolTable.h"
#include "ParseHelper.h"
#include "Scan.h"
#include "ScanContext.h"

#ifdef ENABLE_HLSL
#include "../../hlsl/hlslParseHelper.h"
#include "../../hlsl/hlslParseables.h"
#include "../../hlsl/hlslScanContext.h"
#endif

#include "../Include/ShHandle.h"
#include "../../OGLCompilersDLL/InitializeDll.h"

Expand Down Expand Up @@ -83,16 +78,11 @@ using namespace glslang;
// Create a language specific version of parseables.
TBuiltInParseables* CreateBuiltInParseables(TInfoSink& infoSink, EShSource source)
{
switch (source) {
case EShSourceGlsl: return new TBuiltIns(); // GLSL builtIns
#ifdef ENABLE_HLSL
case EShSourceHlsl: return new TBuiltInParseablesHlsl(); // HLSL intrinsics
#endif

default:
infoSink.info.message(EPrefixInternalError, "Unable to determine source language");
return nullptr;
if (Backend* backend = Backend::Get(source)) {
return backend->CreateBuiltInParseables(infoSink);
}
infoSink.info.message(EPrefixInternalError, "Unable to determine source language");
return nullptr;
}

// Create a language specific version of a parse context.
Expand All @@ -102,23 +92,14 @@ TParseContextBase* CreateParseContext(TSymbolTable& symbolTable, TIntermediate&
SpvVersion spvVersion, bool forwardCompatible, EShMessages messages,
bool parsingBuiltIns, std::string sourceEntryPointName = "")
{
switch (source) {
case EShSourceGlsl: {
if (sourceEntryPointName.size() == 0)
intermediate.setEntryPointName("main");
TString entryPoint = sourceEntryPointName.c_str();
return new TParseContext(symbolTable, intermediate, parsingBuiltIns, version, profile, spvVersion,
language, infoSink, forwardCompatible, messages, &entryPoint);
}
#ifdef ENABLE_HLSL
case EShSourceHlsl:
return new HlslParseContext(symbolTable, intermediate, parsingBuiltIns, version, profile, spvVersion,
language, infoSink, sourceEntryPointName.c_str(), forwardCompatible, messages);
#endif
default:
infoSink.info.message(EPrefixInternalError, "Unable to determine source language");
return nullptr;
if (Backend* backend = Backend::Get(source)) {
return backend->CreateParseContext(symbolTable, intermediate,
version, profile, language, infoSink,
spvVersion, forwardCompatible, messages,
parsingBuiltIns, sourceEntryPointName);
}
infoSink.info.message(EPrefixInternalError, "Unable to determine source language");
return nullptr;
}

// Local mapping functions for making arrays of symbol tables....
Expand Down Expand Up @@ -1322,10 +1303,7 @@ int ShInitialize()
if (PerProcessGPA == nullptr)
PerProcessGPA = new TPoolAllocator();

glslang::TScanContext::fillInKeywordMap();
#ifdef ENABLE_HLSL
glslang::HlslScanContext::fillInKeywordMap();
#endif
Backend::InitializeAll();

return 1;
}
Expand Down Expand Up @@ -1424,10 +1402,7 @@ int ShFinalize()
PerProcessGPA = nullptr;
}

glslang::TScanContext::deleteKeywordMap();
#ifdef ENABLE_HLSL
glslang::HlslScanContext::deleteKeywordMap();
#endif
Backend::TerminateAll();

return 1;
}
Expand Down
7 changes: 7 additions & 0 deletions glslang/Public/ShaderLang.h
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,13 @@ bool InitializeProcess();
// Call once per process to tear down everything
void FinalizeProcess();

#ifdef ENABLE_HLSL
// Call to enable the HLSL backend before doing any other compiler/linker
// operations.
// Implemented in the HLSL library.
void RegisterHLSLBackend();
#endif

// Resource type for IO resolver
enum TResourceType {
EResSampler,
Expand Down
Loading

0 comments on commit e13b079

Please sign in to comment.