All external library header references consistently include framework references. Cleanup references to external library headers that are no longer required. Simplify and consolidate external library header paths in Xcode projects. Add MVK_EXCLUDE_SPIRV_TOOLS build option to avoid use of SPIRV-Tools library. Remove all other references to headers within SPIRV-Tools library.
261 lines
10 KiB
C++
261 lines
10 KiB
C++
/*
|
|
* GLSLToSPIRVConverter.cpp
|
|
*
|
|
* Copyright (c) 2014-2019 The Brenwill Workshop Ltd. (http://www.brenwill.com)
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#include "GLSLToSPIRVConverter.h"
|
|
#include "MVKCommonEnvironment.h"
|
|
#include "SPIRVToMSLConverter.h"
|
|
#include "SPIRVSupport.h"
|
|
#include "MVKStrings.h"
|
|
#include <glslang/SPIRV/GlslangToSpv.h>
|
|
#include <sstream>
|
|
|
|
using namespace std;
|
|
using namespace mvk;
|
|
|
|
|
|
#pragma mark -
|
|
#pragma mark GLSLToSPIRVConverter
|
|
|
|
/** Configures the specified limit resources structure used by the GLSL compiler. */
|
|
void configureGLSLCompilerResources(TBuiltInResource* glslCompilerResources);
|
|
|
|
/** Returns the GLSL compiler language type corresponding to the specified MoltenVK shader stage. */
|
|
EShLanguage eshLanguageFromMVKGLSLConversionShaderStage(const MVKGLSLConversionShaderStage mvkShaderStage);
|
|
|
|
MVK_PUBLIC_SYMBOL bool GLSLToSPIRVConverter::convert(MVKGLSLConversionShaderStage shaderStage,
|
|
bool shouldLogGLSL,
|
|
bool shouldLogSPIRV) {
|
|
_wasConverted = true;
|
|
_resultLog.clear();
|
|
_spirv.clear();
|
|
|
|
if (shouldLogGLSL) { logGLSL("Converting"); }
|
|
|
|
EShMessages messages = (EShMessages)(EShMsgDefault | EShMsgSpvRules | EShMsgVulkanRules);
|
|
|
|
EShLanguage stage = eshLanguageFromMVKGLSLConversionShaderStage(shaderStage);
|
|
TBuiltInResource glslCompilerResources;
|
|
configureGLSLCompilerResources(&glslCompilerResources);
|
|
const char *glslStrings[1];
|
|
glslStrings[0] = _glsl.data();
|
|
|
|
// Create and compile a shader from the source code
|
|
glslang::TShader glslShader(stage);
|
|
glslShader.setStrings(glslStrings, 1);
|
|
if (glslShader.parse(&glslCompilerResources, 100, false, messages)) {
|
|
if (shouldLogGLSL) {
|
|
logMsg(glslShader.getInfoLog());
|
|
logMsg(glslShader.getInfoDebugLog());
|
|
}
|
|
} else {
|
|
logError(glslShader.getInfoLog());
|
|
logError(glslShader.getInfoDebugLog());
|
|
return logError("Error compiling GLSL when converting GLSL to SPIR-V.");
|
|
}
|
|
|
|
// Create and link a shader program containing the single shader
|
|
glslang::TProgram glslProgram;
|
|
glslProgram.addShader(&glslShader);
|
|
if ( !glslProgram.link(messages) ) {
|
|
logError(glslProgram.getInfoLog());
|
|
logError(glslProgram.getInfoDebugLog());
|
|
return logError("Error creating GLSL program when converting GLSL to SPIR-V.");
|
|
}
|
|
|
|
// Output the SPIR-V code from the shader program
|
|
glslang::GlslangToSpv(*glslProgram.getIntermediate(stage), _spirv);
|
|
|
|
if (shouldLogSPIRV) { logSPIRV("Converted"); }
|
|
|
|
return _wasConverted;
|
|
}
|
|
|
|
/** Appends the message text to the result log. */
|
|
void GLSLToSPIRVConverter::logMsg(const char* logMsg) {
|
|
string trimMsg = trim(logMsg);
|
|
if ( !trimMsg.empty() ) {
|
|
_resultLog += trimMsg;
|
|
_resultLog += "\n\n";
|
|
}
|
|
}
|
|
|
|
/** Appends the error text to the result log, sets the wasConverted property to false, and returns it. */
|
|
bool GLSLToSPIRVConverter::logError(const char* errMsg) {
|
|
logMsg(errMsg);
|
|
_wasConverted = false;
|
|
return _wasConverted;
|
|
}
|
|
|
|
/** Appends the SPIR-V to the result log, indicating whether it is being converted or was converted. */
|
|
void GLSLToSPIRVConverter::logSPIRV(const char* opDesc) {
|
|
|
|
string spvLog;
|
|
mvk::logSPIRV(_spirv, spvLog);
|
|
|
|
_resultLog += opDesc;
|
|
_resultLog += " SPIR-V:\n";
|
|
_resultLog += spvLog;
|
|
_resultLog += "\nEnd SPIR-V\n\n";
|
|
}
|
|
|
|
/** Validates that the SPIR-V code will disassemble during logging. */
|
|
bool GLSLToSPIRVConverter::validateSPIRV() {
|
|
if (_spirv.size() < 5) { return false; }
|
|
if (_spirv[0] != spv::MagicNumber) { return false; }
|
|
if (_spirv[4] != 0) { return false; }
|
|
return true;
|
|
}
|
|
|
|
/** Appends the GLSL to the result log, indicating whether it is being converted or was converted. */
|
|
void GLSLToSPIRVConverter::logGLSL(const char* opDesc) {
|
|
_resultLog += opDesc;
|
|
_resultLog += " GLSL:\n";
|
|
_resultLog += _glsl;
|
|
_resultLog += "\nEnd GLSL\n\n";
|
|
}
|
|
|
|
|
|
#pragma mark -
|
|
#pragma mark Support functions
|
|
|
|
void configureGLSLCompilerResources(TBuiltInResource* glslCompilerResources) {
|
|
glslCompilerResources->maxLights = 32;
|
|
glslCompilerResources->maxClipPlanes = 6;
|
|
glslCompilerResources->maxTextureUnits = 32;
|
|
glslCompilerResources->maxTextureCoords = 32;
|
|
glslCompilerResources->maxVertexAttribs = 64;
|
|
glslCompilerResources->maxVertexUniformComponents = 4096;
|
|
glslCompilerResources->maxVaryingFloats = 64;
|
|
glslCompilerResources->maxVertexTextureImageUnits = 32;
|
|
glslCompilerResources->maxCombinedTextureImageUnits = 80;
|
|
glslCompilerResources->maxTextureImageUnits = 32;
|
|
glslCompilerResources->maxFragmentUniformComponents = 4096;
|
|
glslCompilerResources->maxDrawBuffers = 32;
|
|
glslCompilerResources->maxVertexUniformVectors = 128;
|
|
glslCompilerResources->maxVaryingVectors = 8;
|
|
glslCompilerResources->maxFragmentUniformVectors = 16;
|
|
glslCompilerResources->maxVertexOutputVectors = 16;
|
|
glslCompilerResources->maxFragmentInputVectors = 15;
|
|
glslCompilerResources->minProgramTexelOffset = -8;
|
|
glslCompilerResources->maxProgramTexelOffset = 7;
|
|
glslCompilerResources->maxClipDistances = 8;
|
|
glslCompilerResources->maxComputeWorkGroupCountX = 65535;
|
|
glslCompilerResources->maxComputeWorkGroupCountY = 65535;
|
|
glslCompilerResources->maxComputeWorkGroupCountZ = 65535;
|
|
glslCompilerResources->maxComputeWorkGroupSizeX = 1024;
|
|
glslCompilerResources->maxComputeWorkGroupSizeY = 1024;
|
|
glslCompilerResources->maxComputeWorkGroupSizeZ = 64;
|
|
glslCompilerResources->maxComputeUniformComponents = 1024;
|
|
glslCompilerResources->maxComputeTextureImageUnits = 16;
|
|
glslCompilerResources->maxComputeImageUniforms = 8;
|
|
glslCompilerResources->maxComputeAtomicCounters = 8;
|
|
glslCompilerResources->maxComputeAtomicCounterBuffers = 1;
|
|
glslCompilerResources->maxVaryingComponents = 60;
|
|
glslCompilerResources->maxVertexOutputComponents = 64;
|
|
glslCompilerResources->maxGeometryInputComponents = 64;
|
|
glslCompilerResources->maxGeometryOutputComponents = 128;
|
|
glslCompilerResources->maxFragmentInputComponents = 128;
|
|
glslCompilerResources->maxImageUnits = 8;
|
|
glslCompilerResources->maxCombinedImageUnitsAndFragmentOutputs = 8;
|
|
glslCompilerResources->maxCombinedShaderOutputResources = 8;
|
|
glslCompilerResources->maxImageSamples = 0;
|
|
glslCompilerResources->maxVertexImageUniforms = 0;
|
|
glslCompilerResources->maxTessControlImageUniforms = 0;
|
|
glslCompilerResources->maxTessEvaluationImageUniforms = 0;
|
|
glslCompilerResources->maxGeometryImageUniforms = 0;
|
|
glslCompilerResources->maxFragmentImageUniforms = 8;
|
|
glslCompilerResources->maxCombinedImageUniforms = 8;
|
|
glslCompilerResources->maxGeometryTextureImageUnits = 16;
|
|
glslCompilerResources->maxGeometryOutputVertices = 256;
|
|
glslCompilerResources->maxGeometryTotalOutputComponents = 1024;
|
|
glslCompilerResources->maxGeometryUniformComponents = 1024;
|
|
glslCompilerResources->maxGeometryVaryingComponents = 64;
|
|
glslCompilerResources->maxTessControlInputComponents = 128;
|
|
glslCompilerResources->maxTessControlOutputComponents = 128;
|
|
glslCompilerResources->maxTessControlTextureImageUnits = 16;
|
|
glslCompilerResources->maxTessControlUniformComponents = 1024;
|
|
glslCompilerResources->maxTessControlTotalOutputComponents = 4096;
|
|
glslCompilerResources->maxTessEvaluationInputComponents = 128;
|
|
glslCompilerResources->maxTessEvaluationOutputComponents = 128;
|
|
glslCompilerResources->maxTessEvaluationTextureImageUnits = 16;
|
|
glslCompilerResources->maxTessEvaluationUniformComponents = 1024;
|
|
glslCompilerResources->maxTessPatchComponents = 120;
|
|
glslCompilerResources->maxPatchVertices = 32;
|
|
glslCompilerResources->maxTessGenLevel = 64;
|
|
glslCompilerResources->maxViewports = 16;
|
|
glslCompilerResources->maxVertexAtomicCounters = 0;
|
|
glslCompilerResources->maxTessControlAtomicCounters = 0;
|
|
glslCompilerResources->maxTessEvaluationAtomicCounters = 0;
|
|
glslCompilerResources->maxGeometryAtomicCounters = 0;
|
|
glslCompilerResources->maxFragmentAtomicCounters = 8;
|
|
glslCompilerResources->maxCombinedAtomicCounters = 8;
|
|
glslCompilerResources->maxAtomicCounterBindings = 1;
|
|
glslCompilerResources->maxVertexAtomicCounterBuffers = 0;
|
|
glslCompilerResources->maxTessControlAtomicCounterBuffers = 0;
|
|
glslCompilerResources->maxTessEvaluationAtomicCounterBuffers = 0;
|
|
glslCompilerResources->maxGeometryAtomicCounterBuffers = 0;
|
|
glslCompilerResources->maxFragmentAtomicCounterBuffers = 1;
|
|
glslCompilerResources->maxCombinedAtomicCounterBuffers = 1;
|
|
glslCompilerResources->maxAtomicCounterBufferSize = 16384;
|
|
glslCompilerResources->maxTransformFeedbackBuffers = 4;
|
|
glslCompilerResources->maxTransformFeedbackInterleavedComponents = 64;
|
|
glslCompilerResources->maxCullDistances = 8;
|
|
glslCompilerResources->maxCombinedClipAndCullDistances = 8;
|
|
glslCompilerResources->maxSamples = 4;
|
|
glslCompilerResources->limits.nonInductiveForLoops = 1;
|
|
glslCompilerResources->limits.whileLoops = 1;
|
|
glslCompilerResources->limits.doWhileLoops = 1;
|
|
glslCompilerResources->limits.generalUniformIndexing = 1;
|
|
glslCompilerResources->limits.generalAttributeMatrixVectorIndexing = 1;
|
|
glslCompilerResources->limits.generalVaryingIndexing = 1;
|
|
glslCompilerResources->limits.generalSamplerIndexing = 1;
|
|
glslCompilerResources->limits.generalVariableIndexing = 1;
|
|
glslCompilerResources->limits.generalConstantMatrixVectorIndexing = 1;
|
|
}
|
|
|
|
EShLanguage eshLanguageFromMVKGLSLConversionShaderStage(const MVKGLSLConversionShaderStage mvkShaderStage) {
|
|
switch (mvkShaderStage) {
|
|
case kMVKGLSLConversionShaderStageVertex: return EShLangVertex;
|
|
case kMVKGLSLConversionShaderStageTessControl: return EShLangTessControl;
|
|
case kMVKGLSLConversionShaderStageTessEval: return EShLangTessEvaluation;
|
|
case kMVKGLSLConversionShaderStageGeometry: return EShLangGeometry;
|
|
case kMVKGLSLConversionShaderStageFragment: return EShLangFragment;
|
|
case kMVKGLSLConversionShaderStageCompute: return EShLangCompute;
|
|
default: return EShLangVertex;
|
|
}
|
|
}
|
|
|
|
|
|
#pragma mark Library initialization
|
|
|
|
/**
|
|
* Called automatically when the framework is loaded and initialized.
|
|
*
|
|
* Initialize the
|
|
*/
|
|
static bool _wasShaderConverterInitialized = false;
|
|
__attribute__((constructor)) static void MVKShaderConverterInit() {
|
|
if (_wasShaderConverterInitialized ) { return; }
|
|
|
|
glslang::InitializeProcess();
|
|
|
|
_wasShaderConverterInitialized = true;
|
|
}
|
|
|
|
|