https://github.com/shader-slang/slang
Raw File
Tip revision: 01efe34dbef2be952298075abd8d36cc67ac9f4e authored by Yong He on 04 March 2024, 21:14:21 UTC
Add `IGlobalSession::getSessionDescDigest`. (#3669)
Tip revision: 01efe34
slang-compiler-options.cpp
#include "slang-compiler-options.h"
#include "slang-compiler.h"

namespace Slang
{
    void CompilerOptionSet::load(uint32_t count, slang::CompilerOptionEntry* entries)
    {
        for (uint32_t i = 0; i < count; i++)
        {
            CompilerOptionValue value;
            value.kind = entries[i].value.kind;
            value.intValue = entries[i].value.intValue0;
            value.intValue2 = entries[i].value.intValue1;
            if (value.kind == CompilerOptionValueKind::String)
            {
                value.stringValue = entries[i].value.stringValue0;
                value.stringValue2 = entries[i].value.stringValue1;
            }
            add(entries[i].name, value);
        }
    }

    void CompilerOptionSet::writeCommandLineArgs(Session* globalSession, StringBuilder& sb)
    {
        for (auto& option : options)
        {
            auto optionInfoIndex = globalSession->m_commandOptions.findOptionByUserValue(CommandOptions::UserValue(option.key));
            if (optionInfoIndex == -1)
                continue;
            auto optionInfo = globalSession->m_commandOptions.getOptionAt(optionInfoIndex);
            auto nameCommaIndex = optionInfo.names.indexOf(',');
            if (nameCommaIndex == -1) nameCommaIndex = optionInfo.names.getLength();
            auto name = optionInfo.names.head(nameCommaIndex);
            switch (option.key)
            {
                case CompilerOptionName::Capability:
                    for (auto v : option.value)
                    {
                        sb << " " << optionInfo.names << " " << v.stringValue;
                    }
                    break;
                case CompilerOptionName::Include:
                    for (auto v : option.value)
                    {
                        sb << " -I \"" << v.stringValue << "\"";
                    }
                    break;
                case CompilerOptionName::MacroDefine:
                    for (auto v : option.value)
                    {
                        sb << " -D" << v.stringValue;
                        if (v.stringValue2.getLength())
                            sb << "=" << v.stringValue2;
                    }
                    break;
                case CompilerOptionName::VulkanBindShift:  // intValue0 (higher 8 bits): kind; intValue0(higher bits): set; intValue1: shift
                    for (auto v : option.value)
                    {
                        uint8_t kind;
                        int set, shift;
                        v.unpackInt3(kind, set, shift);
                        switch ((HLSLToVulkanLayoutOptions::Kind)(kind))
                        {
                        case HLSLToVulkanLayoutOptions::Kind::UnorderedAccess:
                            sb << " -fvk-u-shift";
                            break;
                        case HLSLToVulkanLayoutOptions::Kind::Sampler:
                            sb << " -fvk-s-shift";
                            break;
                        case HLSLToVulkanLayoutOptions::Kind::ShaderResource:
                            sb << " -fvk-t-shift";
                            break;
                        case HLSLToVulkanLayoutOptions::Kind::ConstantBuffer:
                            sb << " -fvk-b-shift";
                            break;
                        default:
                            continue;
                        }
                        sb << " " << shift << " " << set;
                    }
                    break;
                case CompilerOptionName::VulkanBindShiftAll:            // intValue0: set; intValue1: shift
                    for (auto v : option.value)
                    {
                        sb << " -fvk-all-shift " << v.intValue2 << " " << v.intValue;
                    }
                    break;
                case CompilerOptionName::VulkanBindGlobals:          // intValue0: index; intValue1: set
                    for (auto v : option.value)
                    {
                        sb << " " << name << v.intValue << " " << v.intValue2;
                    }
                    break;
                case CompilerOptionName::Optimization:
                    for (auto v : option.value)
                    {
                        sb << " -O" << v.intValue;
                    }
                    break;
                case CompilerOptionName::DownstreamArgs:
                    for (auto v : option.value)
                    {
                        List<UnownedStringSlice> lines;
                        StringUtil::split(v.stringValue2.getUnownedSlice(), '\n', lines);
                        for (auto l : lines)
                        {
                            sb << " -x" << v.stringValue << " " << l.trim();
                        }
                    }
                    break;
                case CompilerOptionName::EmitSpirvDirectly:
                case CompilerOptionName::GLSLForceScalarLayout:
                case CompilerOptionName::MatrixLayoutRow:
                case CompilerOptionName::MatrixLayoutColumn:
                case CompilerOptionName::VulkanInvertY:
                case CompilerOptionName::VulkanUseEntryPointName:
                case CompilerOptionName::VulkanUseGLLayout:
                case CompilerOptionName::VulkanEmitReflection:
                case CompilerOptionName::EnableEffectAnnotations:
                case CompilerOptionName::DefaultImageFormatUnknown:
                case CompilerOptionName::DisableDynamicDispatch:
                case CompilerOptionName::DisableSpecialization:
                case CompilerOptionName::DumpIntermediates:
                    if (option.value.getCount() && option.value[0].intValue != 0)
                        sb << " " << name;
                    break;
            }
        }
    }

    void CompilerOptionSet::buildHash(DigestBuilder<SHA1>& builder)
    {
        for (auto& kv : options)
        {
            builder.append(kv.key);
            builder.append(kv.value.getCount());
            for (auto& v : kv.value)
            {
                if (v.kind == CompilerOptionValueKind::Int)
                {
                    builder.append(v.intValue);
                }
                else
                {
                    builder.append(v.stringValue);
                    builder.append(v.stringValue2);
                }
            }
        }
    }

    bool CompilerOptionSet::allowDuplicate(CompilerOptionName name)
    {
        switch (name)
        {
        case CompilerOptionName::Include:
        case CompilerOptionName::MacroDefine:
        case CompilerOptionName::WarningsAsErrors:
        case CompilerOptionName::DisableWarning:
        case CompilerOptionName::DisableWarnings:
        case CompilerOptionName::EnableWarning:
        case CompilerOptionName::Capability:
        case CompilerOptionName::DownstreamArgs:
        case CompilerOptionName::VulkanBindShift:
        case CompilerOptionName::VulkanBindShiftAll:
            return true;
        }
        return false;
    }
    CompilerOptionValue Slang::CompilerOptionSet::getDefault(CompilerOptionName name)
    {
        switch (name)
        {
        case CompilerOptionName::Optimization:
            return CompilerOptionValue::fromEnum(OptimizationLevel::Default);
        default:
            return CompilerOptionValue();
        }
    }

    SlangTargetFlags CompilerOptionSet::getTargetFlags()
    {
        SlangTargetFlags result = 0;
        if (getBoolOption(CompilerOptionName::DumpIr))
            result |= SLANG_TARGET_FLAG_DUMP_IR;
        if (getBoolOption(CompilerOptionName::GenerateWholeProgram))
            result |= SLANG_TARGET_FLAG_GENERATE_WHOLE_PROGRAM;
        if (getBoolOption(CompilerOptionName::EmitSpirvDirectly))
            result |= SLANG_TARGET_FLAG_GENERATE_SPIRV_DIRECTLY;
        if (getBoolOption(CompilerOptionName::ParameterBlocksUseRegisterSpaces))
            result |= SLANG_TARGET_FLAG_PARAMETER_BLOCKS_USE_REGISTER_SPACES;
        return result;
    }

    void CompilerOptionSet::setTargetFlags(SlangTargetFlags flags)
    {
        set(CompilerOptionName::DumpIr, (flags & SLANG_TARGET_FLAG_DUMP_IR) != 0);
        set(CompilerOptionName::GenerateWholeProgram, (flags & SLANG_TARGET_FLAG_GENERATE_WHOLE_PROGRAM) != 0);
        set(CompilerOptionName::EmitSpirvDirectly, (flags & SLANG_TARGET_FLAG_GENERATE_SPIRV_DIRECTLY) != 0);
        set(CompilerOptionName::ParameterBlocksUseRegisterSpaces, (flags & SLANG_TARGET_FLAG_PARAMETER_BLOCKS_USE_REGISTER_SPACES) != 0);
    }

    void CompilerOptionSet::addTargetFlags(SlangTargetFlags flags)
    {
        if ((flags & SLANG_TARGET_FLAG_DUMP_IR))
            set(CompilerOptionName::DumpIr, true);

        if ((flags & SLANG_TARGET_FLAG_GENERATE_WHOLE_PROGRAM) != 0)
            set(CompilerOptionName::GenerateWholeProgram, true);

        if ((flags & SLANG_TARGET_FLAG_GENERATE_SPIRV_DIRECTLY) != 0)
            set(CompilerOptionName::EmitSpirvDirectly, true);

        if ((flags & SLANG_TARGET_FLAG_PARAMETER_BLOCKS_USE_REGISTER_SPACES) != 0)
            set(CompilerOptionName::ParameterBlocksUseRegisterSpaces, true);
    }
    MatrixLayoutMode CompilerOptionSet::getMatrixLayoutMode()
    {
        if (getBoolOption(CompilerOptionName::MatrixLayoutRow))
            return kMatrixLayoutMode_RowMajor;
        if (getBoolOption(CompilerOptionName::MatrixLayoutColumn))
            return kMatrixLayoutMode_ColumnMajor;

        return (MatrixLayoutMode)kMatrixLayoutMode_RowMajor;
    }

    void CompilerOptionSet::setMatrixLayoutMode(MatrixLayoutMode mode)
    {
        options.remove(CompilerOptionName::MatrixLayoutColumn);
        options.remove(CompilerOptionName::MatrixLayoutRow);
        if (mode == kMatrixLayoutMode_ColumnMajor)
            set(CompilerOptionName::MatrixLayoutColumn, true);
        if (mode == kMatrixLayoutMode_RowMajor)
            set(CompilerOptionName::MatrixLayoutRow, true);
    }

    Profile CompilerOptionSet::getProfile()
    {
        if (auto profileRaw = getEnumOption<Profile::RawEnum>(CompilerOptionName::Profile))
            return Profile(profileRaw);
        return Profile();
    }

    void CompilerOptionSet::setProfile(Profile profile)
    {
        set(CompilerOptionName::Profile, (int)profile.raw);
    }

    ProfileVersion CompilerOptionSet::getProfileVersion()
    {
        if (auto profileRaw = getEnumOption<Profile::RawEnum>(CompilerOptionName::Profile))
            return Profile(profileRaw).getVersion();
        return ProfileVersion::Unknown;
    }

    void CompilerOptionSet::setProfileVersion(ProfileVersion version)
    {
        Profile profile;
        if (auto profileRaw = getEnumOption<Profile::RawEnum>(CompilerOptionName::Profile))
            profile = Profile(profileRaw);
        profile.setVersion(version);
        set(CompilerOptionName::Profile, (int)profile.raw);
    }

    void CompilerOptionSet::addCapabilityAtom(CapabilityName cap)
    {
        add(CompilerOptionName::Capability, cap);
    }

    List<String> CompilerOptionSet::getDownstreamArgs(String downstreamToolName)
    {
        List<String> result;
        auto downstreamArgsArray = getArray(CompilerOptionName::DownstreamArgs);
        for (auto& argSet : downstreamArgsArray)
        {
            if (argSet.stringValue == downstreamToolName)
            {
                CommandLineArgs args;
                args.deserialize(argSet.stringValue2);
                for (auto arg : args.m_args)
                    result.add(arg.value);
                break;
            }
        }
        return result;
    }

    void CompilerOptionSet::serialize(SerializedOptionsData* outData)
    {
        for (auto& option : options)
        {
            for (auto val : option.value)
            {
                slang::CompilerOptionEntry entry = {};
                entry.name = option.key;
                entry.value.kind = val.kind;
                entry.value.intValue0 = val.intValue;
                entry.value.intValue1 = val.intValue2;
                outData->stringPool.add(val.stringValue);
                entry.value.stringValue0 = val.stringValue.getBuffer();
                outData->stringPool.add(val.stringValue2);
                entry.value.stringValue1 = val.stringValue.getBuffer();
                outData->entries.add(entry);
            }
        }
    }

    void applySettingsToDiagnosticSink(DiagnosticSink* targetSink, DiagnosticSink* outputSink, CompilerOptionSet& options)
    {
        auto disableArray = options.getArray(CompilerOptionName::DisableWarning);
        for (auto& element : disableArray)
        {
            overrideDiagnostic(targetSink, outputSink, element.stringValue.getUnownedSlice(), Severity::Warning, Severity::Disable);
        }
        disableArray = options.getArray(CompilerOptionName::DisableWarnings);
        for (auto& element : disableArray)
        {
            overrideDiagnostics(targetSink, outputSink, element.stringValue.getUnownedSlice(), Severity::Warning, Severity::Disable);
        }
        auto enableArray = options.getArray(CompilerOptionName::EnableWarning);
        for (auto& element : enableArray)
        {
            overrideDiagnostics(targetSink, outputSink, element.stringValue.getUnownedSlice(), Severity::Warning, Severity::Warning);
        }
        auto warningsAsErrorsArray = options.getArray(CompilerOptionName::WarningsAsErrors);
        for (auto& element : warningsAsErrorsArray)
        {
            if (element.stringValue == "all")
                targetSink->setFlag(DiagnosticSink::Flag::TreatWarningsAsErrors);
            else
                overrideDiagnostics(targetSink, outputSink, element.stringValue.getUnownedSlice(), Severity::Warning, Severity::Error);
        }
    }
}
back to top