Add options for tuning the compiling

Related work item: Github #35
This commit is contained in:
Minmin Gong 2019-02-04 23:26:24 -08:00
Родитель e725a6399f
Коммит c45f09a6d8
6 изменённых файлов: 145 добавлений и 14 удалений

Просмотреть файл

@ -100,6 +100,38 @@ namespace ShaderConductor
class SC_API Compiler
{
public:
struct ShaderModel
{
uint8_t major_ver : 6;
uint8_t minor_ver : 2;
uint32_t FullVersion() const noexcept
{
return (major_ver << 2) | minor_ver;
}
bool operator<(const ShaderModel& other) const noexcept
{
return this->FullVersion() < other.FullVersion();
}
bool operator==(const ShaderModel& other) const noexcept
{
return this->FullVersion() == other.FullVersion();
}
bool operator>(const ShaderModel& other) const noexcept
{
return other < *this;
}
bool operator<=(const ShaderModel& other) const noexcept
{
return (*this < other) || (*this == other);
}
bool operator>=(const ShaderModel& other) const noexcept
{
return (*this > other) || (*this == other);
}
};
struct SourceDesc
{
const char* source;
@ -111,6 +143,17 @@ namespace ShaderConductor
std::function<Blob*(const char* includeName)> loadIncludeCallback;
};
struct Options
{
bool packMatricesInRowMajor = true; // Experimental: Decide how a matrix get packed
bool enable16bitTypes = false; // Enable 16-bit types, such as half, uint16_t. Requires shader model 6.2+
bool enableDebugInfo = false; // Embed debug info into the binary
bool disableOptimizations = false; // Force to turn off optimizations. Ignore optimizationLevel below.
int optimizationLevel = 3; // 0 to 3, no optimization to most optimization
ShaderModel shaderModel = { 6, 0 };
};
struct TargetDesc
{
ShadingLanguage language;
@ -134,7 +177,7 @@ namespace ShaderConductor
};
public:
static ResultDesc Compile(const SourceDesc& source, const TargetDesc& target);
static ResultDesc Compile(const SourceDesc& source, const Options& options, const TargetDesc& target);
static ResultDesc Disassemble(const DisassembleDesc& source);
};
} // namespace ShaderConductor

Просмотреть файл

@ -308,7 +308,8 @@ namespace
result.hasError = true;
}
Compiler::ResultDesc CompileToBinary(const Compiler::SourceDesc& source, ShadingLanguage targetLanguage)
Compiler::ResultDesc CompileToBinary(const Compiler::SourceDesc& source, const Compiler::Options& options,
ShadingLanguage targetLanguage)
{
assert((targetLanguage == ShadingLanguage::Dxil) || (targetLanguage == ShadingLanguage::SpirV));
@ -342,7 +343,10 @@ namespace
default:
llvm_unreachable("Invalid shader stage.");
}
shaderProfile += L"_6_0";
shaderProfile.push_back(L'_');
shaderProfile.push_back(L'0' + options.shaderModel.major_ver);
shaderProfile.push_back(L'_');
shaderProfile.push_back(L'0' + options.shaderModel.minor_ver);
std::vector<DxcDefine> dxcDefines;
std::vector<std::wstring> dxcDefineStrings;
@ -386,6 +390,51 @@ namespace
Unicode::UTF8ToUTF16String(source.entryPoint, &entryPointUtf16);
std::vector<std::wstring> dxcArgStrings;
// HLSL matrices are translated into SPIR-V OpTypeMatrixs in a transposed manner,
// See also https://antiagainst.github.io/post/hlsl-for-vulkan-matrices/
if (options.packMatricesInRowMajor)
{
dxcArgStrings.push_back(L"-Zpc");
}
else
{
dxcArgStrings.push_back(L"-Zpr");
}
if (options.enable16bitTypes)
{
if (options.shaderModel >= Compiler::ShaderModel{ 6, 2 })
{
dxcArgStrings.push_back(L"-enable-16bit-types");
}
else
{
throw std::runtime_error("16-bit types requires shader model 6.2 or up.");
}
}
if (options.enableDebugInfo)
{
dxcArgStrings.push_back(L"-Zi");
}
if (options.disableOptimizations)
{
dxcArgStrings.push_back(L"-Od");
}
else
{
if (options.optimizationLevel < 4)
{
dxcArgStrings.push_back(std::wstring(L"-O") + static_cast<wchar_t>(L'0' + options.optimizationLevel));
}
else
{
llvm_unreachable("Invalid optimization level.");
}
}
switch (targetLanguage)
{
case ShadingLanguage::Dxil:
@ -672,7 +721,7 @@ namespace ShaderConductor
delete blob;
}
Compiler::ResultDesc Compiler::Compile(const SourceDesc& source, const TargetDesc& target)
Compiler::ResultDesc Compiler::Compile(const SourceDesc& source, const Options& options, const TargetDesc& target)
{
SourceDesc sourceOverride = source;
if (!sourceOverride.entryPoint || (strlen(sourceOverride.entryPoint) == 0))
@ -685,7 +734,7 @@ namespace ShaderConductor
}
const auto binaryLanguage = target.language == ShadingLanguage::Dxil ? ShadingLanguage::Dxil : ShadingLanguage::SpirV;
auto ret = CompileToBinary(sourceOverride, binaryLanguage);
auto ret = CompileToBinary(sourceOverride, options, binaryLanguage);
if (!ret.hasError && (target.language != binaryLanguage))
{

Просмотреть файл

@ -0,0 +1,20 @@
#version 300
#extension GL_ARB_separate_shader_objects : require
out gl_PerVertex
{
vec4 gl_Position;
};
layout(std140) uniform type_cbVS
{
mat4 wvp;
} cbVS;
in vec4 in_var_POSITION;
void main()
{
gl_Position = cbVS.wvp * in_var_POSITION;
}

Просмотреть файл

@ -91,13 +91,14 @@ namespace
}
}
void HlslToAnyTest(const std::string& name, const Compiler::SourceDesc& source, const Compiler::TargetDesc& target, bool expectSuccess)
void HlslToAnyTest(const std::string& name, const Compiler::SourceDesc& source, const Compiler::Options& options,
const Compiler::TargetDesc& target, bool expectSuccess)
{
static const std::string extMap[] = { "dxil", "spv", "hlsl", "glsl", "essl", "msl" };
static_assert(sizeof(extMap) / sizeof(extMap[0]) == static_cast<uint32_t>(ShadingLanguage::NumShadingLanguages),
"extMap doesn't match with the number of shading languages.");
const auto result = Compiler::Compile(source, target);
const auto result = Compiler::Compile(source, options, target);
if (expectSuccess)
{
@ -145,7 +146,7 @@ namespace
}
}
void RunTests(ShadingLanguage targetSl)
void RunTests(ShadingLanguage targetSl, const Compiler::Options& options = {})
{
for (const auto& combination : m_combinations)
{
@ -153,7 +154,8 @@ namespace
{
if (std::get<1>(target).language == targetSl)
{
HlslToAnyTest(std::get<0>(combination), std::get<1>(combination), std::get<1>(target), std::get<0>(target));
HlslToAnyTest(std::get<0>(combination), std::get<1>(combination), options, std::get<1>(target),
std::get<0>(target));
}
}
}
@ -404,6 +406,21 @@ namespace
RunTests(ShadingLanguage::Glsl);
}
TEST_F(VertexShaderTest, ToGlslColumnMajor)
{
const std::string fileName = TEST_DATA_DIR "Input/Transform_VS.hlsl";
std::vector<uint8_t> input = LoadFile(fileName, true);
TrimTailingZeros(&input);
const std::string source = std::string(reinterpret_cast<char*>(input.data()), input.size());
Compiler::Options options;
options.packMatricesInRowMajor = false;
HlslToAnyTest("Transform_VS_ColumnMajor", { source.c_str(), fileName.c_str(), nullptr, ShaderStage::VertexShader }, options,
{ ShadingLanguage::Glsl, "300" }, true);
}
TEST_F(VertexShaderTest, ToEssl)
{
RunTests(ShadingLanguage::Essl);
@ -528,7 +545,7 @@ namespace
const std::string source = std::string(reinterpret_cast<char*>(input.data()), input.size());
const auto result =
Compiler::Compile({ source.c_str(), fileName.c_str(), "main", ShaderStage::PixelShader }, { ShadingLanguage::Glsl, "30" });
Compiler::Compile({ source.c_str(), fileName.c_str(), "main", ShaderStage::PixelShader }, {}, { ShadingLanguage::Glsl, "30" });
EXPECT_FALSE(result.hasError);
EXPECT_EQ(result.errorWarningMsg, nullptr);
@ -550,7 +567,7 @@ namespace
const std::string source = std::string(reinterpret_cast<char*>(input.data()), input.size());
const auto result =
Compiler::Compile({ source.c_str(), fileName.c_str(), "main", ShaderStage::PixelShader }, { ShadingLanguage::Glsl, "30" });
Compiler::Compile({ source.c_str(), fileName.c_str(), "main", ShaderStage::PixelShader }, {}, { ShadingLanguage::Glsl, "30" });
EXPECT_TRUE(result.hasError);
const char* errorStr = reinterpret_cast<const char*>(result.errorWarningMsg->Data());
@ -569,7 +586,7 @@ namespace
const std::string source = std::string(reinterpret_cast<char*>(input.data()), input.size());
const auto result =
Compiler::Compile({ source.c_str(), fileName.c_str(), "main", ShaderStage::PixelShader }, { ShadingLanguage::Glsl, "30" });
Compiler::Compile({ source.c_str(), fileName.c_str(), "main", ShaderStage::PixelShader }, {}, { ShadingLanguage::Glsl, "30" });
EXPECT_FALSE(result.hasError);
EXPECT_EQ(result.errorWarningMsg, nullptr);

Просмотреть файл

@ -167,7 +167,7 @@ int main(int argc, char** argv)
try
{
const auto result = Compiler::Compile(sourceDesc, targetDesc);
const auto result = Compiler::Compile(sourceDesc, {}, targetDesc);
if (result.errorWarningMsg != nullptr)
{

Просмотреть файл

@ -39,13 +39,15 @@ void Compile(SourceDescription* source, TargetDescription* target, ResultDescrip
sourceDesc.defines = nullptr;
sourceDesc.numDefines = 0;
Compiler::Options options;
Compiler::TargetDesc targetDesc;
targetDesc.language = target->shadingLanguage;
targetDesc.version = target->version;
try
{
const auto translation = Compiler::Compile(sourceDesc, targetDesc);
const auto translation = Compiler::Compile(sourceDesc, options, targetDesc);
if (translation.errorWarningMsg != nullptr)
{