Panagiotis Christopoulos Charitos 5 лет назад
Родитель
Сommit
ac37fce193

+ 2 - 1
shaders/Ssr.ankiprog

@@ -62,7 +62,8 @@ Vec3 raymarch(Vec3 r, Vec3 n, Vec3 viewPos, Vec2 uv, F32 depth)
 
 	// Compute an end point p1. This point is supposed to fall in front of the near plane. Add a small padding to near
 	// to avoid having p1 touching the near plane.
-	const Vec3 p1 = p0 + r * (-p0.z - (u_near + 0.1));
+	const F32 p0DistFromNear = -p0.z - (u_near + 0.1); // aka testPlane(near, p0)
+	const Vec3 p1 = p0 + r * p0DistFromNear; // Whatever the direction of r, p1 won't touch the near plane
 
 	// Start point
 	const Vec3 start = Vec3(uv, depth);

+ 0 - 1
src/anki/Gr.h

@@ -18,7 +18,6 @@
 #include <anki/gr/Fence.h>
 #include <anki/gr/GrManager.h>
 #include <anki/gr/RenderGraph.h>
-#include <anki/gr/ShaderCompiler.h>
 
 #include <anki/gr/utils/ClassGpuAllocator.h>
 #include <anki/gr/utils/FrameGpuAllocator.h>

+ 0 - 549
src/anki/gr/ShaderCompiler.cpp

@@ -1,549 +0,0 @@
-// Copyright (C) 2009-2020, Panagiotis Christopoulos Charitos and contributors.
-// All rights reserved.
-// Code licensed under the BSD License.
-// http://www.anki3d.org/LICENSE
-
-#include <anki/gr/ShaderCompiler.h>
-#include <anki/gr/GrManager.h>
-#include <anki/util/Tracer.h>
-#include <anki/util/StringList.h>
-#include <anki/util/Filesystem.h>
-#include <anki/util/File.h>
-
-#if ANKI_COMPILER_GCC_COMPATIBLE
-#	pragma GCC diagnostic push
-#	pragma GCC diagnostic ignored "-Wundef"
-#	pragma GCC diagnostic ignored "-Wconversion"
-#endif
-#include <glslang/Public/ShaderLang.h>
-#include <glslang/SPIRV/GlslangToSpv.h>
-#include <glslang/StandAlone/DirStackFileIncluder.h>
-#include <SPIRV-Cross/spirv_glsl.hpp>
-#if ANKI_COMPILER_GCC_COMPATIBLE
-#	pragma GCC diagnostic pop
-#endif
-
-namespace anki
-{
-
-void ShaderCompilerOptions::setFromGrManager(const GrManager& gr)
-{
-#if ANKI_GR_BACKEND_VULKAN
-	m_outLanguage = ShaderLanguage::SPIRV;
-#else
-	m_outLanguage = ShaderLanguage::GLSL;
-#endif
-	m_gpuCapabilities = gr.getDeviceCapabilities();
-	m_bindlessLimits = gr.getBindlessLimits();
-}
-
-static const Array<const char*, U(ShaderType::COUNT)> SHADER_NAME = {
-	{"VERTEX", "TESSELATION_CONTROL", "TESSELATION_EVALUATION", "GEOMETRY", "FRAGMENT", "COMPUTE"}};
-
-static const char* SHADER_HEADER = R"(#version 450 core
-#define ANKI_BACKEND_%s 1
-#define ANKI_BACKEND_MINOR %u
-#define ANKI_BACKEND_MAJOR %u
-#define ANKI_VENDOR_%s 1
-#define ANKI_%s_SHADER 1
-
-#if defined(ANKI_BACKEND_GL)
-#	error GL is Deprecated
-#else
-#	define gl_VertexID gl_VertexIndex
-#	define gl_InstanceID gl_InstanceIndex
-#
-#	extension GL_EXT_control_flow_attributes : require
-#	define ANKI_UNROLL [[unroll]]
-#	define ANKI_LOOP [[dont_unroll]]
-#	define ANKI_BRANCH [[branch]]
-#	define ANKI_FLATTEN [[flatten]]
-#
-#	if ANKI_BACKEND_MAJOR == 1 && ANKI_BACKEND_MINOR >= 1
-#		extension GL_KHR_shader_subgroup_vote : require
-#		extension GL_KHR_shader_subgroup_ballot : require
-#		extension GL_KHR_shader_subgroup_shuffle : require
-#		extension GL_KHR_shader_subgroup_arithmetic : require
-#	endif
-#	extension GL_EXT_samplerless_texture_functions : require
-#	extension GL_EXT_shader_image_load_formatted : require
-#	extension GL_EXT_nonuniform_qualifier : enable
-#
-#	define ANKI_MAX_BINDLESS_TEXTURES %u
-#	define ANKI_MAX_BINDLESS_IMAGES %u
-#	define ANKI_BINDLESS_SET(set_) \
-		layout(set = set_, binding = 0) uniform utexture2D u_bindlessTexturesU2d[ANKI_MAX_BINDLESS_TEXTURES]; \
-		layout(set = set_, binding = 0) uniform texture2D u_bindlessTextures2d[ANKI_MAX_BINDLESS_TEXTURES]; \
-		layout(set = set_, binding = 1) uniform readonly uimage2D u_bindlessImages[ANKI_MAX_BINDLESS_IMAGES];
-#endif
-
-#define F32 float
-#define Vec2 vec2
-#define Vec3 vec3
-#define Vec4 vec4
-
-#define U32 uint
-#define UVec2 uvec2
-#define UVec3 uvec3
-#define UVec4 uvec4
-
-#define I32 int
-#define IVec2 ivec2
-#define IVec3 ivec3
-#define IVec4 ivec4
-
-#define Mat3 mat3
-#define Mat4 mat4
-#define Mat3x4 mat3x4
-
-#define Bool bool
-
-%s)";
-
-static EShLanguage ankiToGlslangShaderType(ShaderType shaderType)
-{
-	EShLanguage gslangShader;
-	switch(shaderType)
-	{
-	case ShaderType::VERTEX:
-		gslangShader = EShLangVertex;
-		break;
-	case ShaderType::FRAGMENT:
-		gslangShader = EShLangFragment;
-		break;
-	case ShaderType::TESSELLATION_EVALUATION:
-		gslangShader = EShLangTessEvaluation;
-		break;
-	case ShaderType::TESSELLATION_CONTROL:
-		gslangShader = EShLangTessControl;
-		break;
-	case ShaderType::GEOMETRY:
-		gslangShader = EShLangGeometry;
-		break;
-	case ShaderType::COMPUTE:
-		gslangShader = EShLangCompute;
-		break;
-	default:
-		ANKI_ASSERT(0);
-		gslangShader = EShLangCount;
-	};
-
-	return gslangShader;
-}
-
-static TBuiltInResource setLimits()
-{
-	TBuiltInResource c = {};
-
-	c.maxLights = 32;
-	c.maxClipPlanes = 6;
-	c.maxTextureUnits = 32;
-	c.maxTextureCoords = 32;
-	c.maxVertexAttribs = 64;
-	c.maxVertexUniformComponents = 4096;
-	c.maxVaryingFloats = 64;
-	c.maxVertexTextureImageUnits = 32;
-	c.maxCombinedTextureImageUnits = 80;
-	c.maxTextureImageUnits = 32;
-	c.maxFragmentUniformComponents = 4096;
-	c.maxDrawBuffers = 32;
-	c.maxVertexUniformVectors = 128;
-	c.maxVaryingVectors = 8;
-	c.maxFragmentUniformVectors = 16;
-	c.maxVertexOutputVectors = 16;
-	c.maxFragmentInputVectors = 15;
-	c.minProgramTexelOffset = -8;
-	c.maxProgramTexelOffset = 7;
-	c.maxClipDistances = 8;
-	c.maxComputeWorkGroupCountX = 65535;
-	c.maxComputeWorkGroupCountY = 65535;
-	c.maxComputeWorkGroupCountZ = 65535;
-	c.maxComputeWorkGroupSizeX = 1024;
-	c.maxComputeWorkGroupSizeY = 1024;
-	c.maxComputeWorkGroupSizeZ = 64;
-	c.maxComputeUniformComponents = 1024;
-	c.maxComputeTextureImageUnits = 16;
-	c.maxComputeImageUniforms = 8;
-	c.maxComputeAtomicCounters = 8;
-	c.maxComputeAtomicCounterBuffers = 1;
-	c.maxVaryingComponents = 60;
-	c.maxVertexOutputComponents = 64;
-	c.maxGeometryInputComponents = 64;
-	c.maxGeometryOutputComponents = 128;
-	c.maxFragmentInputComponents = 128;
-	c.maxImageUnits = 8;
-	c.maxCombinedImageUnitsAndFragmentOutputs = 8;
-	c.maxCombinedShaderOutputResources = 8;
-	c.maxImageSamples = 0;
-	c.maxVertexImageUniforms = 0;
-	c.maxTessControlImageUniforms = 0;
-	c.maxTessEvaluationImageUniforms = 0;
-	c.maxGeometryImageUniforms = 0;
-	c.maxFragmentImageUniforms = 8;
-	c.maxCombinedImageUniforms = 8;
-	c.maxGeometryTextureImageUnits = 16;
-	c.maxGeometryOutputVertices = 256;
-	c.maxGeometryTotalOutputComponents = 1024;
-	c.maxGeometryUniformComponents = 1024;
-	c.maxGeometryVaryingComponents = 64;
-	c.maxTessControlInputComponents = 128;
-	c.maxTessControlOutputComponents = 128;
-	c.maxTessControlTextureImageUnits = 16;
-	c.maxTessControlUniformComponents = 1024;
-	c.maxTessControlTotalOutputComponents = 4096;
-	c.maxTessEvaluationInputComponents = 128;
-	c.maxTessEvaluationOutputComponents = 128;
-	c.maxTessEvaluationTextureImageUnits = 16;
-	c.maxTessEvaluationUniformComponents = 1024;
-	c.maxTessPatchComponents = 120;
-	c.maxPatchVertices = 32;
-	c.maxTessGenLevel = 64;
-	c.maxViewports = 16;
-	c.maxVertexAtomicCounters = 0;
-	c.maxTessControlAtomicCounters = 0;
-	c.maxTessEvaluationAtomicCounters = 0;
-	c.maxGeometryAtomicCounters = 0;
-	c.maxFragmentAtomicCounters = 8;
-	c.maxCombinedAtomicCounters = 8;
-	c.maxAtomicCounterBindings = 1;
-	c.maxVertexAtomicCounterBuffers = 0;
-	c.maxTessControlAtomicCounterBuffers = 0;
-	c.maxTessEvaluationAtomicCounterBuffers = 0;
-	c.maxGeometryAtomicCounterBuffers = 0;
-	c.maxFragmentAtomicCounterBuffers = 1;
-	c.maxCombinedAtomicCounterBuffers = 1;
-	c.maxAtomicCounterBufferSize = 16384;
-	c.maxTransformFeedbackBuffers = 4;
-	c.maxTransformFeedbackInterleavedComponents = 64;
-	c.maxCullDistances = 8;
-	c.maxCombinedClipAndCullDistances = 8;
-	c.maxSamples = 4;
-
-	c.limits.nonInductiveForLoops = 1;
-	c.limits.whileLoops = 1;
-	c.limits.doWhileLoops = 1;
-	c.limits.generalUniformIndexing = 1;
-	c.limits.generalAttributeMatrixVectorIndexing = 1;
-	c.limits.generalVaryingIndexing = 1;
-	c.limits.generalSamplerIndexing = 1;
-	c.limits.generalVariableIndexing = 1;
-	c.limits.generalConstantMatrixVectorIndexing = 1;
-
-	return c;
-}
-
-static const TBuiltInResource GLSLANG_LIMITS = setLimits();
-
-static void preappendAnkiSpecific(CString source, const ShaderCompilerOptions& options, StringAuto& out)
-{
-	// Gen the new source
-	out.sprintf(SHADER_HEADER,
-		(options.m_outLanguage == ShaderLanguage::GLSL) ? "GL" : "VULKAN",
-		options.m_gpuCapabilities.m_minorApiVersion,
-		options.m_gpuCapabilities.m_majorApiVersion,
-		&GPU_VENDOR_STR[options.m_gpuCapabilities.m_gpuVendor][0],
-		SHADER_NAME[options.m_shaderType],
-		options.m_bindlessLimits.m_bindlessTextureCount,
-		options.m_bindlessLimits.m_bindlessImageCount,
-		&source[0]);
-}
-
-I32 ShaderCompiler::m_refcount = {0};
-Mutex ShaderCompiler::m_refcountMtx;
-
-ShaderCompiler::ShaderCompiler(GenericMemoryPoolAllocator<U8> alloc)
-	: m_alloc(alloc)
-{
-	LockGuard<Mutex> lock(m_refcountMtx);
-
-	const I32 refcount = m_refcount++;
-	ANKI_ASSERT(refcount >= 0);
-
-	if(refcount == 0)
-	{
-		glslang::InitializeProcess();
-	}
-}
-
-ShaderCompiler::~ShaderCompiler()
-{
-	LockGuard<Mutex> lock(m_refcountMtx);
-
-	const I32 refcount = m_refcount--;
-	ANKI_ASSERT(refcount >= 0);
-
-	if(refcount == 1)
-	{
-		glslang::FinalizeProcess();
-	}
-}
-
-Error ShaderCompiler::preprocessCommon(CString in, const ShaderCompilerOptions& options, StringAuto& out) const
-{
-	const EShLanguage stage = ankiToGlslangShaderType(options.m_shaderType);
-
-	glslang::TShader shader(stage);
-	Array<const char*, 1> csrc = {{&in[0]}};
-	shader.setStrings(&csrc[0], 1);
-
-	DirStackFileIncluder includer;
-	EShMessages messages = EShMsgDefault;
-	std::string glslangOut;
-	if(!shader.preprocess(&GLSLANG_LIMITS, 450, ENoProfile, false, false, messages, &glslangOut, includer))
-	{
-		ShaderCompiler::logShaderErrorCode(shader.getInfoLog(), in, m_alloc);
-		return Error::USER_DATA;
-	}
-
-	out.append(glslangOut.c_str());
-
-	return Error::NONE;
-}
-
-Error ShaderCompiler::genSpirv(CString src, const ShaderCompilerOptions& options, DynamicArrayAuto<U8>& spirv) const
-{
-	const EShLanguage stage = ankiToGlslangShaderType(options.m_shaderType);
-
-	EShMessages messages = EShMsgSpvRules;
-	if(options.m_outLanguage == ShaderLanguage::SPIRV)
-	{
-		messages = static_cast<EShMessages>(messages | EShMsgVulkanRules);
-	}
-
-	// Setup the shader
-	glslang::EShTargetLanguageVersion langVersion;
-	if(options.m_outLanguage == ShaderLanguage::SPIRV && options.m_gpuCapabilities.m_minorApiVersion > 0)
-	{
-		langVersion = glslang::EShTargetSpv_1_3;
-	}
-	else
-	{
-		langVersion = glslang::EShTargetSpv_1_0;
-	}
-
-	glslang::TShader shader(stage);
-	Array<const char*, 1> csrc = {{&src[0]}};
-	shader.setStrings(&csrc[0], 1);
-	shader.setEnvTarget(glslang::EShTargetSpv, langVersion);
-	if(!shader.parse(&GLSLANG_LIMITS, 100, false, messages))
-	{
-		ShaderCompiler::logShaderErrorCode(shader.getInfoLog(), src, m_alloc);
-		return Error::USER_DATA;
-	}
-
-	// Setup the program
-	glslang::TProgram program;
-	program.addShader(&shader);
-
-	if(!program.link(messages))
-	{
-		ANKI_GR_LOGE("glslang failed to link a shader");
-		return Error::USER_DATA;
-	}
-
-	// Gen SPIRV
-	glslang::SpvOptions spvOptions;
-	spvOptions.optimizeSize = true;
-	spvOptions.disableOptimizer = false;
-	std::vector<unsigned int> glslangSpirv;
-	glslang::GlslangToSpv(*program.getIntermediate(stage), glslangSpirv, &spvOptions);
-
-	// Store
-	spirv.resize(U32(glslangSpirv.size() * sizeof(unsigned int)));
-	memcpy(&spirv[0], &glslangSpirv[0], spirv.getSizeInBytes());
-
-	return Error::NONE;
-}
-
-Error ShaderCompiler::preprocess(
-	CString source, const ShaderCompilerOptions& options, const StringList& defines, StringAuto& out) const
-{
-	ANKI_ASSERT(!source.isEmpty() && source.getLength() > 0);
-
-	ANKI_TRACE_SCOPED_EVENT(GR_SHADER_COMPILE);
-
-	// Append defines
-	StringAuto newSource(m_alloc);
-	auto it = defines.getBegin();
-	auto end = defines.getEnd();
-	while(it != end)
-	{
-		newSource.append("#define ");
-		newSource.append(it->toCString());
-		newSource.append(" = (");
-		++it;
-		ANKI_ASSERT(it != end);
-		newSource.append(it->toCString());
-		newSource.append(")\n");
-	}
-	newSource.append(source);
-
-	// Add the extra code
-	StringAuto fullSrc(m_alloc);
-	preappendAnkiSpecific(newSource.toCString(), options, fullSrc);
-
-	// Do the work
-	ANKI_CHECK(preprocessCommon(fullSrc.toCString(), options, out));
-
-	return Error::NONE;
-}
-
-Error ShaderCompiler::compile(CString source,
-	const ShaderCompilerOptions& options,
-	DynamicArrayAuto<U8>& bin,
-	CString finalSourceDumpFilename) const
-{
-	ANKI_ASSERT(!source.isEmpty() && source.getLength() > 0);
-	Error err = Error::NONE;
-
-	ANKI_TRACE_SCOPED_EVENT(GR_SHADER_COMPILE);
-
-	// Create the context
-	StringAuto finalSrc(m_alloc);
-	preappendAnkiSpecific(source, options, finalSrc);
-
-	// Compile
-	if(options.m_outLanguage == ShaderLanguage::GLSL)
-	{
-#if 0
-		std::vector<unsigned int> spv;
-		err = genSpirv(ctx, spv);
-		if(!err)
-		{
-			spirv_cross::CompilerGLSL cross(spv);
-			std::string newSrc = cross.compile();
-
-			bin.resize(newSrc.length() + 1);
-			memcpy(&bin[0], &newSrc[0], bin.getSize());
-		}
-#else
-		// Preprocess the source because MESA sucks and can't do it
-		StringAuto out(m_alloc);
-		ANKI_CHECK(preprocessCommon(finalSrc.toCString(), options, out));
-
-		bin.resize(U32(out.getLength() + 1));
-		memcpy(&bin[0], &out[0], bin.getSizeInBytes());
-#endif
-	}
-	else
-	{
-		ANKI_CHECK(genSpirv(finalSrc.toCString(), options, bin));
-	}
-
-	// Dump
-	if(finalSourceDumpFilename)
-	{
-		File file;
-		ANKI_CHECK(file.open(finalSourceDumpFilename, FileOpenFlag::WRITE));
-		ANKI_CHECK(file.write(finalSrc.cstr(), finalSrc.getLength() - 1));
-	}
-
-	return err;
-}
-
-void ShaderCompiler::logShaderErrorCode(CString error, CString source, GenericMemoryPoolAllocator<U8> alloc)
-{
-	StringAuto prettySrc(alloc);
-	StringListAuto lines(alloc);
-
-	static const char* padding = "==============================================================================";
-
-	lines.splitString(source, '\n', true);
-
-	I lineno = 0;
-	for(auto it = lines.getBegin(); it != lines.getEnd(); ++it)
-	{
-		++lineno;
-		StringAuto tmp(alloc);
-
-		if(!it->isEmpty())
-		{
-			tmp.sprintf("%8d: %s\n", lineno, &(*it)[0]);
-		}
-		else
-		{
-			tmp.sprintf("%8d:\n", lineno);
-		}
-
-		prettySrc.append(tmp);
-	}
-
-	ANKI_GR_LOGE("Shader compilation failed:\n%s\n%s\n%s\n%s\n%s\n%s",
-		padding,
-		&error[0],
-		padding,
-		&prettySrc[0],
-		padding,
-		&error[0]);
-}
-
-Error ShaderCompilerCache::compile(CString source,
-	U64* hash,
-	const ShaderCompilerOptions& options,
-	DynamicArrayAuto<U8>& bin,
-	Bool dumpShaderSource) const
-{
-	const Error err = compileInternal(source, hash, options, bin, dumpShaderSource);
-	if(err)
-	{
-		ANKI_GR_LOGE("Failed to compile or retrieve shader from the cache");
-	}
-
-	return err;
-}
-
-Error ShaderCompilerCache::compileInternal(CString source,
-	U64* hash,
-	const ShaderCompilerOptions& options,
-	DynamicArrayAuto<U8>& bin,
-	Bool dumpShaderSource) const
-{
-	ANKI_ASSERT(!source.isEmpty() && source.getLength() > 0);
-
-	// Compute hash
-	U64 fhash;
-	if(hash)
-	{
-		fhash = *hash;
-		ANKI_ASSERT(fhash != 0);
-	}
-	else
-	{
-		fhash = computeHash(&source[0], source.getLength());
-	}
-
-	fhash = appendHash(&options, sizeof(options), fhash);
-
-	// Search the cache
-	StringAuto fname(m_alloc);
-	fname.sprintf("%s/%llu.shdrbin", m_cacheDir.cstr(), fhash);
-	if(fileExists(fname.toCString()))
-	{
-		File file;
-		ANKI_CHECK(file.open(fname.toCString(), FileOpenFlag::READ | FileOpenFlag::BINARY));
-
-		PtrSize size = file.getSize();
-		bin.resize(U32(size));
-		ANKI_CHECK(file.read(&bin[0], bin.getSize()));
-	}
-	else
-	{
-		ANKI_GR_LOGI("%s not found in cache. Will compile", fname.cstr());
-
-		StringAuto dumpSrcFname(m_alloc);
-		if(dumpShaderSource)
-		{
-			dumpSrcFname.sprintf("%s/%llu.glsl", m_cacheDir.cstr(), fhash);
-		}
-
-		ANKI_CHECK(m_compiler.compile(source, options, bin, (dumpSrcFname) ? dumpSrcFname.toCString() : CString()));
-
-		File file;
-		ANKI_CHECK(file.open(fname.toCString(), FileOpenFlag::WRITE | FileOpenFlag::BINARY));
-		ANKI_CHECK(file.write(&bin[0], bin.getSize()));
-	}
-
-	return Error::NONE;
-}
-
-} // end namespace anki

+ 0 - 125
src/anki/gr/ShaderCompiler.h

@@ -1,125 +0,0 @@
-// Copyright (C) 2009-2020, Panagiotis Christopoulos Charitos and contributors.
-// All rights reserved.
-// Code licensed under the BSD License.
-// http://www.anki3d.org/LICENSE
-
-#pragma once
-
-#include <anki/gr/Common.h>
-#include <anki/util/DynamicArray.h>
-
-namespace anki
-{
-
-// Forward
-class StringList;
-
-/// @addtogroup graphics
-/// @{
-
-enum class ShaderLanguage : U8
-{
-	GLSL,
-	SPIRV,
-	COUNT
-};
-
-/// ShaderCompiler compile options.
-class ShaderCompilerOptions
-{
-public:
-	ShaderLanguage m_outLanguage;
-	ShaderType m_shaderType;
-	GpuDeviceCapabilities m_gpuCapabilities;
-	BindlessLimits m_bindlessLimits;
-
-	ShaderCompilerOptions()
-	{
-		// Zero it because it will be hashed
-		zeroMemory(*this);
-		m_outLanguage = ShaderLanguage::COUNT;
-		m_shaderType = ShaderType::COUNT;
-		::new(&m_gpuCapabilities) GpuDeviceCapabilities();
-	}
-
-	void setFromGrManager(const GrManager& gr);
-};
-
-/// Shader compiler. It's backend agnostic.
-class ShaderCompiler
-{
-public:
-	ShaderCompiler(GenericMemoryPoolAllocator<U8> alloc);
-
-	~ShaderCompiler();
-
-	/// Compile a shader.
-	/// @param source The source in GLSL.
-	/// @param options Compile options.
-	/// @param bin The output binary.
-	/// @param finalSourceDumpFilename Write the final source to this filename if it's not empty.
-	ANKI_USE_RESULT Error compile(CString source,
-		const ShaderCompilerOptions& options,
-		DynamicArrayAuto<U8>& bin,
-		CString finalSourceDumpFilename = {}) const;
-
-	ANKI_USE_RESULT Error preprocess(
-		CString source, const ShaderCompilerOptions& options, const StringList& defines, StringAuto& out) const;
-
-	ANKI_INTERNAL static void logShaderErrorCode(CString error, CString source, GenericMemoryPoolAllocator<U8> alloc);
-
-private:
-	GenericMemoryPoolAllocator<U8> m_alloc;
-	static I32 m_refcount;
-	static Mutex m_refcountMtx;
-
-	ANKI_USE_RESULT Error genSpirv(
-		CString src, const ShaderCompilerOptions& options, DynamicArrayAuto<U8>& spirv) const;
-
-	ANKI_USE_RESULT Error preprocessCommon(CString in, const ShaderCompilerOptions& options, StringAuto& out) const;
-};
-
-/// Like ShaderCompiler but on steroids. It uses a cache to avoid compiling shaders else it calls
-/// ShaderCompiler::compile
-class ShaderCompilerCache
-{
-public:
-	ShaderCompilerCache(GenericMemoryPoolAllocator<U8> alloc, CString cacheDir)
-		: m_alloc(alloc)
-		, m_compiler(alloc)
-	{
-		ANKI_ASSERT(!cacheDir.isEmpty());
-		m_cacheDir.create(alloc, cacheDir);
-	}
-
-	~ShaderCompilerCache()
-	{
-		m_cacheDir.destroy(m_alloc);
-	}
-
-	/// Compile a shader.
-	/// @param source The source in GLSL.
-	/// @param sourceHash Optional hash of the source. If it's nullptr then the @a source will be hashed.
-	/// @param options Compile options.
-	/// @param bin The output binary.
-	/// @param dumpShaderSource If true dump the shaders' source as well.
-	ANKI_USE_RESULT Error compile(CString source,
-		U64* hash,
-		const ShaderCompilerOptions& options,
-		DynamicArrayAuto<U8>& bin,
-		Bool dumpShaderSource = false) const;
-
-private:
-	GenericMemoryPoolAllocator<U8> m_alloc;
-	ShaderCompiler m_compiler;
-	String m_cacheDir;
-
-	ANKI_USE_RESULT Error compileInternal(CString source,
-		U64* hash,
-		const ShaderCompilerOptions& options,
-		DynamicArrayAuto<U8>& bin,
-		Bool dumpShaderSource) const;
-};
-/// @}
-
-} // end namespace anki

+ 0 - 4
src/anki/resource/ResourceManager.cpp

@@ -8,7 +8,6 @@
 #include <anki/resource/AnimationResource.h>
 #include <anki/util/Logger.h>
 #include <anki/core/ConfigSet.h>
-#include <anki/gr/ShaderCompiler.h>
 
 #include <anki/resource/MaterialResource2.h>
 #include <anki/resource/MeshResource.h>
@@ -34,7 +33,6 @@ ResourceManager::~ResourceManager()
 	m_cacheDir.destroy(m_alloc);
 	m_alloc.deleteInstance(m_asyncLoader);
 	m_alloc.deleteInstance(m_transferGpuAlloc);
-	m_alloc.deleteInstance(m_shaderCompiler);
 }
 
 Error ResourceManager::init(ResourceManagerInitInfo& init)
@@ -66,8 +64,6 @@ Error ResourceManager::init(ResourceManagerInitInfo& init)
 	m_transferGpuAlloc = m_alloc.newInstance<TransferGpuAllocator>();
 	ANKI_CHECK(m_transferGpuAlloc->init(init.m_config->getNumberU32("rsrc_transferScratchMemorySize"), m_gr, m_alloc));
 
-	m_shaderCompiler = m_alloc.newInstance<ShaderCompilerCache>(m_alloc, m_cacheDir.toCString());
-
 	return Error::NONE;
 }
 

+ 0 - 7
src/anki/resource/ResourceManager.h

@@ -200,12 +200,6 @@ public:
 		return *m_asyncLoader;
 	}
 
-	ANKI_INTERNAL const ShaderCompilerCache& getShaderCompiler() const
-	{
-		ANKI_ASSERT(m_shaderCompiler);
-		return *m_shaderCompiler;
-	}
-
 	/// Get the number of times loadResource() was called.
 	ANKI_INTERNAL U64 getLoadingRequestCount() const
 	{
@@ -227,7 +221,6 @@ private:
 	U64 m_uuid = 0;
 	U64 m_loadRequestCount = 0;
 	TransferGpuAllocator* m_transferGpuAlloc = nullptr;
-	ShaderCompilerCache* m_shaderCompiler = nullptr;
 	Bool m_dumpShaderSource = false;
 };
 /// @}

+ 0 - 857
src/anki/resource/ShaderProgramPreProcessor.cpp

@@ -1,857 +0,0 @@
-// Copyright (C) 2009-2020, Panagiotis Christopoulos Charitos and contributors.
-// All rights reserved.
-// Code licensed under the BSD License.
-// http://www.anki3d.org/LICENSE
-
-#include <anki/resource/ShaderProgramPreProcessor.h>
-#include <anki/resource/ResourceFilesystem.h>
-
-namespace anki
-{
-
-#define ANKI_PP_ERROR(errStr_) \
-	ANKI_RESOURCE_LOGE("%s: " errStr_, fname.cstr()); \
-	return Error::USER_DATA
-
-#define ANKI_PP_ERROR_MALFORMED() \
-	ANKI_RESOURCE_LOGE("%s: Malformed expression: %s", fname.cstr(), line.cstr()); \
-	return Error::USER_DATA
-
-static ANKI_USE_RESULT Error computeShaderVariableDataType(const CString& str, ShaderVariableDataType& out)
-{
-	Error err = Error::NONE;
-
-	if(str == "I32")
-	{
-		out = ShaderVariableDataType::INT;
-	}
-	else if(str == "IVec2")
-	{
-		out = ShaderVariableDataType::IVEC2;
-	}
-	else if(str == "IVec3")
-	{
-		out = ShaderVariableDataType::IVEC3;
-	}
-	else if(str == "IVec4")
-	{
-		out = ShaderVariableDataType::IVEC4;
-	}
-	else if(str == "U32")
-	{
-		out = ShaderVariableDataType::UINT;
-	}
-	else if(str == "UVec2")
-	{
-		out = ShaderVariableDataType::UVEC2;
-	}
-	else if(str == "UVec3")
-	{
-		out = ShaderVariableDataType::UVEC3;
-	}
-	else if(str == "UVec4")
-	{
-		out = ShaderVariableDataType::UVEC4;
-	}
-	else if(str == "F32")
-	{
-		out = ShaderVariableDataType::FLOAT;
-	}
-	else if(str == "Vec2")
-	{
-		out = ShaderVariableDataType::VEC2;
-	}
-	else if(str == "Vec3")
-	{
-		out = ShaderVariableDataType::VEC3;
-	}
-	else if(str == "Vec4")
-	{
-		out = ShaderVariableDataType::VEC4;
-	}
-	else if(str == "Mat3")
-	{
-		out = ShaderVariableDataType::MAT3;
-	}
-	else if(str == "Mat4")
-	{
-		out = ShaderVariableDataType::MAT4;
-	}
-	else if(str == "texture2D")
-	{
-		out = ShaderVariableDataType::TEXTURE_2D;
-	}
-	else if(str == "texture2DArray")
-	{
-		out = ShaderVariableDataType::TEXTURE_2D_ARRAY;
-	}
-	else if(str == "textureCube")
-	{
-		out = ShaderVariableDataType::TEXTURE_CUBE;
-	}
-	else if(str == "sampler")
-	{
-		out = ShaderVariableDataType::SAMPLER;
-	}
-	else
-	{
-		ANKI_RESOURCE_LOGE("Incorrect variable type %s", &str[0]);
-		err = Error::USER_DATA;
-	}
-
-	return err;
-}
-
-Error ShaderProgramPreprocessor::parse()
-{
-	ANKI_ASSERT(!m_fname.isEmpty());
-	ANKI_ASSERT(m_lines.isEmpty());
-
-	CString fname = m_fname.toCString();
-
-	// Parse recursively
-	ANKI_CHECK(parseFile(m_fname.toCString(), 0));
-
-	// Checks
-	if(m_foundInstancedInput != (m_instancedMutatorIdx != MAX_U32))
-	{
-		ANKI_PP_ERROR("If there is an instanced mutator there should be at least one instanced input");
-	}
-
-	if(!!(m_shaderTypes & ShaderTypeBit::COMPUTE))
-	{
-		if(m_shaderTypes != ShaderTypeBit::COMPUTE)
-		{
-			ANKI_PP_ERROR("Can't combine compute shader with other types of shaders");
-		}
-
-		if(m_instancedMutatorIdx != MAX_U32)
-		{
-			ANKI_PP_ERROR("Can't have instanced mutators in compute programs");
-		}
-	}
-	else
-	{
-		if(!(m_shaderTypes & ShaderTypeBit::VERTEX))
-		{
-			ANKI_PP_ERROR("Missing vertex shader");
-		}
-
-		if(!(m_shaderTypes & ShaderTypeBit::FRAGMENT))
-		{
-			ANKI_PP_ERROR("Missing fragment shader");
-		}
-	}
-
-	if(m_insideShader)
-	{
-		ANKI_PP_ERROR("Forgot a \"pragma anki end\"");
-	}
-
-	// Compute the final source
-	{
-		if(m_instancedMutatorIdx < MAX_U32)
-		{
-			StringAuto str(m_alloc);
-			str.sprintf("#define GEN_INSTANCE_COUNT_ %s\n", m_mutators[m_instancedMutatorIdx].m_name.cstr());
-			m_finalSource.append(str.toCString());
-		}
-
-		{
-			StringAuto str(m_alloc);
-			str.sprintf("#define GEN_SET_ %u\n", m_set);
-			m_finalSource.append(str.toCString());
-		}
-
-		// The UBO
-		if(m_uboStructLines.getSize() > 0)
-		{
-			m_uboStructLines.pushFront("struct GenUniforms_ {");
-			m_uboStructLines.pushBack("};");
-
-			m_uboStructLines.pushBack("#if USE_PUSH_CONSTANTS == 1");
-			m_uboStructLines.pushBackSprintf(
-				"layout(push_constant, std140, row_major) uniform pc_ {GenUniforms_ gen_unis_;};");
-			m_uboStructLines.pushBack("#else");
-			m_uboStructLines.pushBack(
-				"layout(set = GEN_SET_, binding = 0, row_major) uniform genubo_ {GenUniforms_ gen_unis_;};");
-			m_uboStructLines.pushBack("#endif\n");
-
-			StringAuto ubo(m_alloc);
-			m_uboStructLines.join("\n", ubo);
-			m_finalSource.append(ubo.toCString());
-		}
-
-		// The globals
-		if(m_globalsLines.getSize() > 0)
-		{
-			StringAuto globals(m_alloc);
-			m_globalsLines.pushBack("\n");
-			m_globalsLines.join("\n", globals);
-
-			m_finalSource.append(globals.toCString());
-		}
-
-		// Last is the source
-		{
-			StringAuto code(m_alloc);
-			m_lines.join("\n", code);
-			m_finalSource.append(code.toCString());
-		}
-	}
-
-	// Free some memory
-	m_lines.destroy();
-	m_globalsLines.destroy();
-	m_uboStructLines.destroy();
-
-	return Error::NONE;
-}
-
-Error ShaderProgramPreprocessor::parseFile(CString fname, U32 depth)
-{
-	// First check the depth
-	if(depth > MAX_INCLUDE_DEPTH)
-	{
-		ANKI_PP_ERROR("The include depth is too high. Probably circular includance");
-	}
-
-	Bool foundPragmaOnce = false;
-
-	// Load file in lines
-	ResourceFilePtr file;
-	ANKI_CHECK(m_fsystem->openFile(fname, file));
-	StringAuto txt(m_alloc);
-	ANKI_CHECK(file->readAllText(txt));
-
-	StringListAuto lines(m_alloc);
-	lines.splitString(txt.toCString(), '\n');
-	if(lines.getSize() < 1)
-	{
-		ANKI_PP_ERROR("Source is empty");
-	}
-
-	// Parse lines
-	for(const String& line : lines)
-	{
-		if(line.find("pragma") != CString::NPOS || line.find("include") != CString::NPOS)
-		{
-			// Possibly a preprocessor directive we care
-			ANKI_CHECK(parseLine(line.toCString(), fname, foundPragmaOnce, depth));
-		}
-		else
-		{
-			// Just append the line
-			m_lines.pushBack(line.toCString());
-		}
-	}
-
-	if(foundPragmaOnce)
-	{
-		// Append the guard
-		m_lines.pushBack("#endif // Include guard");
-	}
-
-	return Error::NONE;
-}
-
-Error ShaderProgramPreprocessor::parseLine(CString line, CString fname, Bool& foundPragmaOnce, U32 depth)
-{
-	// Tokenize
-	DynamicArrayAuto<StringAuto> tokens(m_alloc);
-	tokenizeLine(line, tokens);
-	ANKI_ASSERT(tokens.getSize() > 0);
-
-	const StringAuto* token = tokens.getBegin();
-	const StringAuto* end = tokens.getEnd();
-
-	// Skip the hash
-	Bool foundAloneHash = false;
-	if(*token == "#")
-	{
-		++token;
-		foundAloneHash = true;
-	}
-
-	if((token < end) && ((foundAloneHash && *token == "include") || *token == "#include"))
-	{
-		// We _must_ have an #include
-		ANKI_CHECK(parseInclude(token + 1, end, line, fname, depth));
-	}
-	else if((token < end) && ((foundAloneHash && *token == "pragma") || *token == "#pragma"))
-	{
-		// We may have a #pragma once or a #pragma anki or something else
-
-		++token;
-
-		if(*token == "once")
-		{
-			// Pragma once
-
-			if(foundPragmaOnce)
-			{
-				ANKI_PP_ERROR("Can't have more than one #pragma once per file");
-			}
-
-			if(token + 1 != end)
-			{
-				ANKI_PP_ERROR_MALFORMED();
-			}
-
-			// Add the guard unique for this file
-			foundPragmaOnce = true;
-			const U64 hash = fname.computeHash();
-			m_lines.pushBackSprintf("#ifndef GEN_INCL_GUARD_%llu\n#define GEN_INCL_GUARD_%llu", hash, hash);
-		}
-		else if(*token == "anki")
-		{
-			// Must be a #pragma anki
-
-			++token;
-
-			if(*token == "mutator")
-			{
-				ANKI_CHECK(parsePragmaMutator(token + 1, end, line, fname));
-			}
-			else if(*token == "input")
-			{
-				ANKI_CHECK(parsePragmaInput(token + 1, end, line, fname));
-			}
-			else if(*token == "start")
-			{
-				ANKI_CHECK(parsePragmaStart(token + 1, end, line, fname));
-			}
-			else if(*token == "end")
-			{
-				ANKI_CHECK(parsePragmaEnd(token + 1, end, line, fname));
-			}
-			else if(*token == "descriptor_set")
-			{
-				ANKI_CHECK(parsePragmaDescriptorSet(token + 1, end, line, fname));
-			}
-			else
-			{
-				ANKI_PP_ERROR_MALFORMED();
-			}
-		}
-		else
-		{
-			// Ignore
-			m_lines.pushBack(line);
-		}
-	}
-	else
-	{
-		// Ignore
-		m_lines.pushBack(line);
-	}
-
-	return Error::NONE;
-}
-
-Error ShaderProgramPreprocessor::parseInclude(
-	const StringAuto* begin, const StringAuto* end, CString line, CString fname, U32 depth)
-{
-	// Gather the path
-	StringAuto path(m_alloc);
-	for(; begin < end; ++begin)
-	{
-		path.append(*begin);
-	}
-
-	if(path.isEmpty())
-	{
-		ANKI_PP_ERROR_MALFORMED();
-	}
-
-	// Check
-	const char firstChar = path[0];
-	const char lastChar = path[path.getLength() - 1];
-
-	if((firstChar == '\"' && lastChar == '\"') || (firstChar == '<' && lastChar == '>'))
-	{
-		StringAuto fname2(m_alloc);
-		fname2.create(path.begin() + 1, path.begin() + path.getLength() - 1);
-
-		if(parseFile(fname2.toCString(), depth + 1))
-		{
-			ANKI_PP_ERROR("Error parsing include. See previous errors");
-		}
-	}
-	else
-	{
-		ANKI_PP_ERROR_MALFORMED();
-	}
-
-	return Error::NONE;
-}
-
-Error ShaderProgramPreprocessor::parsePragmaMutator(
-	const StringAuto* begin, const StringAuto* end, CString line, CString fname)
-{
-	ANKI_ASSERT(begin && end);
-
-	if(begin >= end)
-	{
-		ANKI_PP_ERROR_MALFORMED();
-	}
-
-	m_mutators.emplaceBack(m_alloc);
-	Mutator& mutator = m_mutators.getBack();
-
-	// Instanced
-	{
-		if(*begin == "instanced")
-		{
-			mutator.m_instanced = true;
-
-			// Check
-			if(m_instancedMutatorIdx != MAX_U32)
-			{
-				ANKI_PP_ERROR("Can't have more than one instanced mutators");
-			}
-
-			m_instancedMutatorIdx = m_mutators.getSize() - 1;
-			++begin;
-		}
-		else
-		{
-			mutator.m_instanced = false;
-		}
-	}
-
-	// Name
-	{
-		if(begin >= end)
-		{
-			// Need to have a name
-			ANKI_PP_ERROR_MALFORMED();
-		}
-
-		// Check for duplicate mutators
-		for(U32 i = 0; i < m_mutators.getSize() - 1; ++i)
-		{
-			if(m_mutators[i].m_name == *begin)
-			{
-				ANKI_PP_ERROR("Duplicate mutator");
-			}
-		}
-
-		mutator.m_name.create(begin->toCString());
-		++begin;
-	}
-
-	// Values
-	{
-		// Gather them
-		for(; begin < end; ++begin)
-		{
-			Mutator::ValueType value = 0;
-
-			if(tokenIsComment(begin->toCString()))
-			{
-				break;
-			}
-
-			if(begin->toNumber(value))
-			{
-				ANKI_PP_ERROR_MALFORMED();
-			}
-
-			mutator.m_values.emplaceBack(value);
-		}
-
-		// Check for correct count
-		if(mutator.m_values.getSize() < 2)
-		{
-			// Mutator with less that 2 values doesn't make sense
-			ANKI_PP_ERROR_MALFORMED();
-		}
-
-		std::sort(mutator.m_values.getBegin(), mutator.m_values.getEnd());
-
-		// Check for duplicates
-		for(U32 i = 1; i < mutator.m_values.getSize(); ++i)
-		{
-			if(mutator.m_values[i - 1] == mutator.m_values[i])
-			{
-				// Can't have the same value
-				ANKI_PP_ERROR_MALFORMED();
-			}
-		}
-	}
-
-	return Error::NONE;
-}
-
-Error ShaderProgramPreprocessor::parsePragmaInput(
-	const StringAuto* begin, const StringAuto* end, CString line, CString fname)
-{
-	ANKI_ASSERT(begin && end);
-
-	if(begin >= end)
-	{
-		ANKI_PP_ERROR_MALFORMED();
-	}
-
-	m_inputs.emplaceBack(m_alloc);
-	Input& input = m_inputs.getBack();
-
-	// const
-	{
-		input.m_const = false;
-		if(*begin == "const")
-		{
-			input.m_const = true;
-			++begin;
-		}
-	}
-
-	// instanced
-	{
-		if(begin >= end)
-		{
-			ANKI_PP_ERROR_MALFORMED();
-		}
-
-		input.m_instanced = false;
-		if(*begin == "instanced")
-		{
-			input.m_instanced = true;
-			m_foundInstancedInput = true;
-			++begin;
-		}
-	}
-
-	// type
-	const StringAuto& dataTypeStr = *begin;
-	{
-		if(begin >= end)
-		{
-			ANKI_PP_ERROR_MALFORMED();
-		}
-
-		if(computeShaderVariableDataType(begin->toCString(), input.m_dataType))
-		{
-			ANKI_PP_ERROR_MALFORMED();
-		}
-		++begin;
-	}
-
-	// name
-	{
-		if(begin >= end)
-		{
-			ANKI_PP_ERROR_MALFORMED();
-		}
-
-		// Check if there are duplicates
-		for(U32 i = 0; i < m_inputs.getSize() - 1; ++i)
-		{
-			if(m_inputs[i].m_name == *begin)
-			{
-				ANKI_PP_ERROR("Duplicate input");
-			}
-		}
-
-		input.m_name.create(begin->toCString());
-		++begin;
-	}
-
-	// Preprocessor expression
-	StringAuto preproc(m_alloc);
-	{
-		// Create the string
-		for(; begin < end; ++begin)
-		{
-			preproc.append(begin->toCString());
-		}
-
-		if(!preproc.isEmpty())
-		{
-			if(preproc.getLength() < 3)
-			{
-				// Too small
-				ANKI_PP_ERROR_MALFORMED();
-			}
-
-			if(preproc[0] != '\"')
-			{
-				// Should start with "
-				ANKI_PP_ERROR_MALFORMED();
-			}
-
-			preproc[0] = ' ';
-
-			if(preproc[preproc.getLength() - 1] != '\"')
-			{
-				// Should end with "
-				ANKI_PP_ERROR_MALFORMED();
-			}
-
-			preproc[preproc.getLength() - 1] = ' ';
-
-			// Only now create it
-			input.m_preproc.create(preproc.toCString());
-		}
-	}
-
-	// Append to source
-
-	const Bool isSampler = input.m_dataType == ShaderVariableDataType::SAMPLER;
-	const Bool isTexture = input.m_dataType >= ShaderVariableDataType::TEXTURE_FIRST
-						   && input.m_dataType <= ShaderVariableDataType::TEXTURE_LAST;
-
-	if(input.m_const)
-	{
-		// Const
-
-		if(isSampler || isTexture || input.m_instanced)
-		{
-			// No const samplers or instanced
-			ANKI_PP_ERROR_MALFORMED();
-		}
-
-		if(preproc)
-		{
-			m_globalsLines.pushBackSprintf("#if %s", preproc.cstr());
-			m_globalsLines.pushBackSprintf("#define %s_DEFINED 1", input.m_name.cstr());
-		}
-
-		m_globalsLines.pushBackSprintf("const %s %s = %s(%s_CONSTVAL);",
-			dataTypeStr.cstr(),
-			input.m_name.cstr(),
-			dataTypeStr.cstr(),
-			input.m_name.cstr());
-
-		if(preproc)
-		{
-			m_globalsLines.pushBack("#else");
-			m_globalsLines.pushBackSprintf("#define %s_DEFINED 0", input.m_name.cstr());
-			m_globalsLines.pushBack("#endif");
-		}
-	}
-	else if(isSampler || isTexture)
-	{
-		// Sampler or texture
-
-		if(input.m_instanced)
-		{
-			// Samplers and textures can't be instanced
-			ANKI_PP_ERROR_MALFORMED();
-		}
-
-		if(preproc)
-		{
-			m_globalsLines.pushBackSprintf("#if %s", preproc.cstr());
-			m_globalsLines.pushBackSprintf("#define %s_DEFINED 1", input.m_name.cstr());
-		}
-
-		m_globalsLines.pushBackSprintf("layout(set = GEN_SET_, binding = %s_BINDING) uniform %s %s;",
-			input.m_name.cstr(),
-			dataTypeStr.cstr(),
-			input.m_name.cstr());
-
-		if(preproc)
-		{
-			m_globalsLines.pushBack("#else");
-			m_globalsLines.pushBackSprintf("#define %s_DEFINED 0", input.m_name.cstr());
-			m_globalsLines.pushBack("#endif");
-		}
-	}
-	else
-	{
-		// UBO
-
-		const char* name = input.m_name.cstr();
-		const char* type = dataTypeStr.cstr();
-
-		if(preproc)
-		{
-			m_uboStructLines.pushBackSprintf("#if %s", preproc.cstr());
-			m_globalsLines.pushBackSprintf("#if %s", preproc.cstr());
-			m_globalsLines.pushBackSprintf("#define %s_DEFINED 1", input.m_name.cstr());
-		}
-
-		if(input.m_instanced)
-		{
-			m_uboStructLines.pushBack("#if GEN_INSTANCE_COUNT_ > 1");
-			m_uboStructLines.pushBackSprintf("%s gen_uni_%s[GEN_INSTANCE_COUNT_];", type, name);
-			m_uboStructLines.pushBack("#else");
-			m_uboStructLines.pushBackSprintf("%s gen_uni_%s;", type, name);
-			m_uboStructLines.pushBack("#endif");
-
-			m_globalsLines.pushBack("#ifdef ANKI_VERTEX_SHADER");
-			m_globalsLines.pushBack("#if GEN_INSTANCE_COUNT_ > 1");
-			m_globalsLines.pushBackSprintf("%s %s = gen_unis_.gen_uni_%s[gl_InstanceID];", type, name, name);
-			m_globalsLines.pushBack("#else");
-			m_globalsLines.pushBackSprintf("%s %s = gen_unis_.gen_uni_%s;", type, name, name);
-			m_globalsLines.pushBack("#endif");
-			m_globalsLines.pushBack("#endif");
-		}
-		else
-		{
-			m_uboStructLines.pushBackSprintf("%s gen_uni_%s;", type, name);
-
-			m_globalsLines.pushBackSprintf("%s %s = gen_unis_.gen_uni_%s;", type, name, name);
-		}
-
-		if(preproc)
-		{
-			m_uboStructLines.pushBack("#endif");
-
-			m_globalsLines.pushBack("#else");
-			m_globalsLines.pushBackSprintf("#define %s_DEFINED 0", name);
-			m_globalsLines.pushBack("#endif");
-		}
-	}
-
-	return Error::NONE;
-}
-
-Error ShaderProgramPreprocessor::parsePragmaStart(
-	const StringAuto* begin, const StringAuto* end, CString line, CString fname)
-{
-	ANKI_ASSERT(begin && end);
-
-	if(begin >= end)
-	{
-		ANKI_PP_ERROR_MALFORMED();
-	}
-
-	ShaderType shaderType = ShaderType::COUNT;
-	if(*begin == "vert")
-	{
-		shaderType = ShaderType::VERTEX;
-		m_lines.pushBack("#ifdef ANKI_VERTEX_SHADER");
-	}
-	else if(*begin == "tessc")
-	{
-		shaderType = ShaderType::TESSELLATION_CONTROL;
-		m_lines.pushBack("#ifdef ANKI_TESSELATION_CONTROL_SHADER");
-	}
-	else if(*begin == "tesse")
-	{
-		shaderType = ShaderType::TESSELLATION_EVALUATION;
-		m_lines.pushBack("#ifdef ANKI_TESSELLATION_EVALUATION_SHADER");
-	}
-	else if(*begin == "geom")
-	{
-		shaderType = ShaderType::GEOMETRY;
-		m_lines.pushBack("#ifdef ANKI_GEOMETRY_SHADER");
-	}
-	else if(*begin == "frag")
-	{
-		shaderType = ShaderType::FRAGMENT;
-		m_lines.pushBack("#ifdef ANKI_FRAGMENT_SHADER");
-	}
-	else if(*begin == "comp")
-	{
-		shaderType = ShaderType::COMPUTE;
-		m_lines.pushBack("#ifdef ANKI_COMPUTE_SHADER");
-	}
-	else
-	{
-		ANKI_PP_ERROR_MALFORMED();
-	}
-
-	++begin;
-	if(begin != end)
-	{
-		// Should be the last token
-		ANKI_PP_ERROR_MALFORMED();
-	}
-
-	// Set the mask
-	ShaderTypeBit mask = ShaderTypeBit(1 << U(shaderType));
-	if(!!(mask & m_shaderTypes))
-	{
-		ANKI_PP_ERROR("Can't have #pragma start <shader> appearing more than once");
-	}
-	m_shaderTypes |= mask;
-
-	// Check bounds
-	if(m_insideShader)
-	{
-		ANKI_PP_ERROR("Can't have #pragma start before you close the previous pragma start");
-	}
-	m_insideShader = true;
-
-	return Error::NONE;
-}
-
-Error ShaderProgramPreprocessor::parsePragmaEnd(
-	const StringAuto* begin, const StringAuto* end, CString line, CString fname)
-{
-	ANKI_ASSERT(begin && end);
-
-	// Check tokens
-	if(begin != end)
-	{
-		ANKI_PP_ERROR_MALFORMED();
-	}
-
-	// Check bounds
-	if(!m_insideShader)
-	{
-		ANKI_PP_ERROR("Can't have #pragma end before you open with a pragma start");
-	}
-	m_insideShader = false;
-
-	// Write code
-	m_lines.pushBack("#endif // Shader guard");
-
-	return Error::NONE;
-}
-
-Error ShaderProgramPreprocessor::parsePragmaDescriptorSet(
-	const StringAuto* begin, const StringAuto* end, CString line, CString fname)
-{
-	ANKI_ASSERT(begin && end);
-
-	if(begin >= end)
-	{
-		ANKI_PP_ERROR_MALFORMED();
-	}
-
-	if(begin->toNumber(m_set))
-	{
-		ANKI_PP_ERROR_MALFORMED();
-	}
-
-	if(m_set >= MAX_DESCRIPTOR_SETS)
-	{
-		ANKI_PP_ERROR("The descriptor set index is too high");
-	}
-
-	return Error::NONE;
-}
-
-void ShaderProgramPreprocessor::tokenizeLine(CString line, DynamicArrayAuto<StringAuto>& tokens)
-{
-	ANKI_ASSERT(line.getLength() > 0);
-
-	StringAuto l(m_alloc);
-	l.create(line);
-
-	// Replace all tabs with spaces
-	for(char& c : l)
-	{
-		if(c == '\t')
-		{
-			c = ' ';
-		}
-	}
-
-	// Split
-	StringListAuto spaceTokens(m_alloc);
-	spaceTokens.splitString(l.toCString(), ' ', false);
-
-	// Create the array
-	for(const String& s : spaceTokens)
-	{
-		tokens.emplaceBack(m_alloc, s.toCString());
-	}
-}
-
-} // end namespace anki

+ 0 - 206
src/anki/resource/ShaderProgramPreProcessor.h

@@ -1,206 +0,0 @@
-// Copyright (C) 2009-2020, Panagiotis Christopoulos Charitos and contributors.
-// All rights reserved.
-// Code licensed under the BSD License.
-// http://www.anki3d.org/LICENSE
-
-#pragma once
-
-#include <anki/resource/Common.h>
-#include <anki/util/StringList.h>
-#include <anki/util/WeakArray.h>
-#include <anki/gr/Common.h>
-
-namespace anki
-{
-
-// Forward
-class ShaderProgramPreprocessor;
-
-/// @addtogroup resource
-/// @{
-
-/// @memberof ShaderProgramPreprocessor
-class ShaderProgramPreprocessorMutator
-{
-	friend ShaderProgramPreprocessor;
-
-public:
-	using ValueType = I32;
-
-	ShaderProgramPreprocessorMutator(GenericMemoryPoolAllocator<U8> alloc)
-		: m_name(alloc)
-		, m_values(alloc)
-	{
-	}
-
-	CString getName() const
-	{
-		return m_name.toCString();
-	}
-
-	ConstWeakArray<I32> getValues() const
-	{
-		return m_values;
-	}
-
-	Bool isInstanced() const
-	{
-		return m_instanced;
-	}
-
-private:
-	StringAuto m_name;
-	DynamicArrayAuto<I32> m_values;
-	Bool m_instanced = false;
-};
-
-/// @memberof ShaderProgramPreprocessor
-class ShaderProgramPreprocessorInput
-{
-	friend ShaderProgramPreprocessor;
-
-public:
-	ShaderProgramPreprocessorInput(GenericMemoryPoolAllocator<U8> alloc)
-		: m_name(alloc)
-		, m_preproc(alloc)
-	{
-	}
-
-	CString getName() const
-	{
-		return m_name.toCString();
-	}
-
-	ShaderVariableDataType getDataType() const
-	{
-		return m_dataType;
-	}
-
-	CString getPreprocessorCondition() const
-	{
-		return (m_preproc) ? m_preproc.toCString() : CString();
-	}
-
-	Bool isInstanced() const
-	{
-		return m_instanced;
-	}
-
-	Bool isConstant() const
-	{
-		return m_const;
-	}
-
-private:
-	StringAuto m_name;
-	StringAuto m_preproc;
-	ShaderVariableDataType m_dataType = ShaderVariableDataType::NONE;
-	Bool m_const = false;
-	Bool m_instanced = false;
-};
-
-/// This is a special preprocessor that run before the usual preprocessor. Its purpose is to add some meta information
-/// in the shader programs.
-///
-/// It supports the following expressions
-/// #include {<> | ""}
-/// #pragma once
-/// #pragma anki mutator [instanced] NAME VALUE0 [VALUE1 [VALUE2] ...]
-/// #pragma anki input [const | instanced] TYPE NAME ["preprocessor expression"]
-/// #pragma anki start {vert | tessc | tesse | geom | frag | comp}
-/// #pragma anki end
-/// #pragma anki descriptor_set <number>
-class ShaderProgramPreprocessor : public NonCopyable
-{
-public:
-	ShaderProgramPreprocessor(CString fname, ResourceFilesystem* fsystem, GenericMemoryPoolAllocator<U8> alloc)
-		: m_alloc(alloc)
-		, m_fname(alloc, fname)
-		, m_fsystem(fsystem)
-		, m_lines(alloc)
-		, m_globalsLines(alloc)
-		, m_uboStructLines(alloc)
-		, m_finalSource(alloc)
-		, m_mutators(alloc)
-		, m_inputs(alloc)
-	{
-	}
-
-	~ShaderProgramPreprocessor()
-	{
-	}
-
-	ANKI_USE_RESULT Error parse();
-
-	CString getSource() const
-	{
-		ANKI_ASSERT(!m_finalSource.isEmpty());
-		return m_finalSource.toCString();
-	}
-
-	ConstWeakArray<ShaderProgramPreprocessorMutator> getMutators() const
-	{
-		return m_mutators;
-	}
-
-	ConstWeakArray<ShaderProgramPreprocessorInput> getInputs() const
-	{
-		return m_inputs;
-	}
-
-	ShaderTypeBit getShaderTypes() const
-	{
-		return m_shaderTypes;
-	}
-
-	U32 getDescritproSet() const
-	{
-		return m_set;
-	}
-
-private:
-	using Mutator = ShaderProgramPreprocessorMutator;
-	using Input = ShaderProgramPreprocessorInput;
-
-	static const U32 MAX_INCLUDE_DEPTH = 8;
-
-	GenericMemoryPoolAllocator<U8> m_alloc;
-	StringAuto m_fname;
-	ResourceFilesystem* m_fsystem = nullptr;
-
-	StringListAuto m_lines; ///< The code.
-	StringListAuto m_globalsLines;
-	StringListAuto m_uboStructLines;
-	StringAuto m_finalSource;
-
-	DynamicArrayAuto<Mutator> m_mutators;
-	DynamicArrayAuto<Input> m_inputs;
-
-	ShaderTypeBit m_shaderTypes = ShaderTypeBit::NONE;
-	Bool m_insideShader = false;
-	U32 m_set = 0;
-	U32 m_instancedMutatorIdx = MAX_U32;
-	Bool m_foundInstancedInput = false;
-
-	ANKI_USE_RESULT Error parseFile(CString fname, U32 depth);
-	ANKI_USE_RESULT Error parseLine(CString line, CString fname, Bool& foundPragmaOnce, U32 depth);
-	ANKI_USE_RESULT Error parseInclude(
-		const StringAuto* begin, const StringAuto* end, CString line, CString fname, U32 depth);
-	ANKI_USE_RESULT Error parsePragmaMutator(
-		const StringAuto* begin, const StringAuto* end, CString line, CString fname);
-	ANKI_USE_RESULT Error parsePragmaInput(const StringAuto* begin, const StringAuto* end, CString line, CString fname);
-	ANKI_USE_RESULT Error parsePragmaStart(const StringAuto* begin, const StringAuto* end, CString line, CString fname);
-	ANKI_USE_RESULT Error parsePragmaEnd(const StringAuto* begin, const StringAuto* end, CString line, CString fname);
-	ANKI_USE_RESULT Error parsePragmaDescriptorSet(
-		const StringAuto* begin, const StringAuto* end, CString line, CString fname);
-
-	void tokenizeLine(CString line, DynamicArrayAuto<StringAuto>& tokens);
-
-	static Bool tokenIsComment(CString token)
-	{
-		return token.getLength() >= 2 && token[0] == '/' && (token[1] == '/' || token[1] == '*');
-	}
-};
-/// @}
-
-} // end namespace anki

+ 12 - 6
src/anki/shader_compiler/ShaderProgramParser.cpp

@@ -715,6 +715,17 @@ Error ShaderProgramParser::parse()
 	return Error::NONE;
 }
 
+void ShaderProgramParser::generateAnkiShaderHeader(
+	const GpuDeviceCapabilities& caps, const BindlessLimits& limits, StringAuto& header)
+{
+	header.sprintf(SHADER_HEADER,
+		caps.m_minorApiVersion,
+		caps.m_majorApiVersion,
+		GPU_VENDOR_STR[caps.m_gpuVendor].cstr(),
+		limits.m_bindlessTextureCount,
+		limits.m_bindlessImageCount);
+}
+
 Error ShaderProgramParser::generateVariant(
 	ConstWeakArray<MutatorValue> mutation, ShaderProgramParserVariant& variant) const
 {
@@ -739,12 +750,7 @@ Error ShaderProgramParser::generateVariant(
 
 	// Create the header
 	StringAuto header(m_alloc);
-	header.sprintf(SHADER_HEADER,
-		m_gpuCapabilities.m_minorApiVersion,
-		m_gpuCapabilities.m_majorApiVersion,
-		GPU_VENDOR_STR[m_gpuCapabilities.m_gpuVendor].cstr(),
-		m_bindlessLimits.m_bindlessTextureCount,
-		m_bindlessLimits.m_bindlessImageCount);
+	generateAnkiShaderHeader(m_gpuCapabilities, m_bindlessLimits, header);
 
 	// Generate souce per stage
 	for(ShaderType shaderType = ShaderType::FIRST; shaderType < ShaderType::COUNT; ++shaderType)

+ 4 - 0
src/anki/shader_compiler/ShaderProgramParser.h

@@ -123,6 +123,10 @@ public:
 		return m_codeSourceHash;
 	}
 
+	/// Generates the common header that will be used by all AnKi shaders.
+	static void generateAnkiShaderHeader(
+		const GpuDeviceCapabilities& caps, const BindlessLimits& limits, StringAuto& header);
+
 private:
 	using Mutator = ShaderProgramParserMutator;
 

+ 8 - 9
tests/gr/Gr.cpp

@@ -10,6 +10,8 @@
 #include <anki/util/HighRezTimer.h>
 #include <anki/core/StagingGpuMemoryManager.h>
 #include <anki/resource/TransferGpuAllocator.h>
+#include <anki/shader_compiler/Glslang.h>
+#include <anki/shader_compiler/ShaderProgramParser.h>
 #include <ctime>
 
 namespace anki
@@ -354,16 +356,13 @@ static ShaderPtr createShader(
 	CString src, ShaderType type, GrManager& gr, ConstWeakArray<ShaderSpecializationConstValue> specVals = {})
 {
 	HeapAllocator<U8> alloc(allocAligned, nullptr);
-	ShaderCompiler comp(alloc);
+	StringAuto header(alloc);
+	ShaderProgramParser::generateAnkiShaderHeader(gr.getDeviceCapabilities(), gr.getBindlessLimits(), header);
+	header.append(src);
+	DynamicArrayAuto<U8> spirv(alloc);
+	ANKI_TEST_EXPECT_NO_ERR(compilerGlslToSpirv(header, type, alloc, spirv));
 
-	ShaderCompilerOptions options;
-	options.setFromGrManager(gr);
-	options.m_shaderType = type;
-
-	DynamicArrayAuto<U8> bin(alloc);
-	ANKI_TEST_EXPECT_NO_ERR(comp.compile(src, options, bin));
-
-	ShaderInitInfo initInf(type, WeakArray<U8>(&bin[0], bin.getSize()));
+	ShaderInitInfo initInf(type, spirv);
 	initInf.m_constValues = specVals;
 
 	return gr.newShader(initInf);

+ 0 - 23
tests/gr/ShaderCompiler.cpp

@@ -1,23 +0,0 @@
-// Copyright (C) 2009-2020, Panagiotis Christopoulos Charitos and contributors.
-// All rights reserved.
-// Code licensed under the BSD License.
-// http://www.anki3d.org/LICENSE
-
-#include <anki/gr/ShaderCompiler.h>
-#include <tests/framework/Framework.h>
-
-ANKI_TEST(Gr, ShaderCompiler)
-{
-	HeapAllocator<U8> alloc(allocAligned, nullptr);
-	ShaderCompilerCache cache(alloc, "./");
-
-	const char* SRC = R"(
-void main()
-{
-})";
-
-	DynamicArrayAuto<U8> bin(alloc);
-	ShaderCompilerOptions options;
-	options.m_outLanguage = ShaderLanguage::SPIRV;
-	ANKI_TEST_EXPECT_NO_ERR(cache.compile(SRC, nullptr, options, bin));
-}