Skip to content
Open
2 changes: 1 addition & 1 deletion Graphics/GraphicsEngine/include/DeviceObjectArchive.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ class DeviceObjectArchive
};

static constexpr Uint32 HeaderMagicNumber = 0xDE00000A;
static constexpr Uint32 ArchiveVersion = 9;
static constexpr Uint32 ArchiveVersion = 10;

struct ArchiveHeader
{
Expand Down
2 changes: 1 addition & 1 deletion Graphics/GraphicsEngine/interface/APIInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
/// \file
/// Diligent API information

#define DILIGENT_API_VERSION 256017
#define DILIGENT_API_VERSION 256018

#include "../../../Primitives/interface/BasicTypes.h"

Expand Down
37 changes: 36 additions & 1 deletion Graphics/GraphicsEngine/interface/Shader.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2019-2025 Diligent Graphics LLC
* Copyright 2019-2026 Diligent Graphics LLC
* Copyright 2015-2019 Egor Yusov
*
* Licensed under the Apache License, Version 2.0 (the "License");
Expand Down Expand Up @@ -419,6 +419,35 @@ DILIGENT_TYPED_ENUM(SHADER_COMPILE_FLAGS, Uint32)
};
DEFINE_FLAG_ENUM_OPERATORS(SHADER_COMPILE_FLAGS);


/// Describes the shader optimization level.
DILIGENT_TYPED_ENUM(SHADER_OPTIMIZATION_LEVEL, Uint8)
{
/// Default optimization level.

/// Each backend uses its historical default optimization behavior.
SHADER_OPTIMIZATION_LEVEL_DEFAULT = 0,

/// Optimization is explicitly disabled regardless of build configuration
/// (DXC `-Od`, FXC `D3DCOMPILE_SKIP_OPTIMIZATION`, no SPIR-V performance pass).
SHADER_OPTIMIZATION_LEVEL_DISABLED,

/// Optimization level 0 (DXC `-O0`, FXC optimization level 0, SPIR-V performance pass).
SHADER_OPTIMIZATION_LEVEL_0,

/// Optimization level 1 (DXC `-O1`, FXC optimization level 1, SPIR-V performance pass).
SHADER_OPTIMIZATION_LEVEL_1,

/// Optimization level 2 (DXC `-O2`, FXC optimization level 2, SPIR-V performance pass).
SHADER_OPTIMIZATION_LEVEL_2,

/// Optimization level 3 (DXC `-O3`, FXC optimization level 3, SPIR-V performance pass).
SHADER_OPTIMIZATION_LEVEL_3,

SHADER_OPTIMIZATION_LEVEL_COUNT
};


// clang-format on


Expand Down Expand Up @@ -525,6 +554,9 @@ struct ShaderCreateInfo
/// Shader compile flags (see Diligent::SHADER_COMPILE_FLAGS).
SHADER_COMPILE_FLAGS CompileFlags DEFAULT_INITIALIZER(SHADER_COMPILE_FLAG_NONE);

/// Shader optimization level. See Diligent::SHADER_OPTIMIZATION_LEVEL.
SHADER_OPTIMIZATION_LEVEL ShaderOptimizationLevel DEFAULT_INITIALIZER(SHADER_OPTIMIZATION_LEVEL_DEFAULT);

/// Whether to load constant buffer reflection information.

/// The reflection information can be queried through
Expand Down Expand Up @@ -675,6 +707,9 @@ struct ShaderCreateInfo
if (CI1.CompileFlags != CI2.CompileFlags)
return false;

if (CI1.ShaderOptimizationLevel != CI2.ShaderOptimizationLevel)
return false;

if (CI1.LoadConstantBufferReflection != CI2.LoadConstantBufferReflection)
return false;

Expand Down
1 change: 1 addition & 0 deletions Graphics/GraphicsEngine/src/PSOSerializer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -520,6 +520,7 @@ bool ShaderSerializer<Mode>::SerializeCI(Serializer<Mode>& Ser,
CI.GLESSLVersion,
CI.MSLVersion,
CI.CompileFlags,
CI.ShaderOptimizationLevel,
CI.LoadConstantBufferReflection,
CI.GLSLExtensions,
CI.WebGPUEmulatedArrayIndexSuffix))
Expand Down
15 changes: 14 additions & 1 deletion Graphics/GraphicsEngineD3DBase/src/ShaderD3DBase.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2019-2025 Diligent Graphics LLC
* Copyright 2019-2026 Diligent Graphics LLC
* Copyright 2015-2019 Egor Yusov
*
* Licensed under the Apache License, Version 2.0 (the "License");
Expand Down Expand Up @@ -122,6 +122,19 @@ HRESULT CompileShader(const char* Source,
if (ShaderCI.CompileFlags & SHADER_COMPILE_FLAG_PACK_MATRIX_ROW_MAJOR)
dwShaderFlags |= D3DCOMPILE_PACK_MATRIX_ROW_MAJOR;

switch (ShaderCI.ShaderOptimizationLevel)
{
case SHADER_OPTIMIZATION_LEVEL_DISABLED: dwShaderFlags |= D3DCOMPILE_SKIP_OPTIMIZATION; break;
case SHADER_OPTIMIZATION_LEVEL_0: dwShaderFlags |= D3DCOMPILE_OPTIMIZATION_LEVEL0; break;
case SHADER_OPTIMIZATION_LEVEL_1: dwShaderFlags |= D3DCOMPILE_OPTIMIZATION_LEVEL1; break;
case SHADER_OPTIMIZATION_LEVEL_2: dwShaderFlags |= D3DCOMPILE_OPTIMIZATION_LEVEL2; break;
case SHADER_OPTIMIZATION_LEVEL_3: dwShaderFlags |= D3DCOMPILE_OPTIMIZATION_LEVEL3; break;
case SHADER_OPTIMIZATION_LEVEL_DEFAULT:
default:
// DEFAULT: no explicit optimization flag (FXC uses its own default level), preserving historical behavior.
break;
}

D3D_SHADER_MACRO Macros[] = {{"D3DCOMPILER", ""}, {}};

D3DIncludeImpl IncludeImpl{ShaderCI.pShaderSourceStreamFactory};
Expand Down
1 change: 1 addition & 0 deletions Graphics/GraphicsEngineVulkan/src/ShaderVkImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ std::vector<uint32_t> CompileShaderGLSLang(const ShaderCreateInfo& Shade
Attribs.UseRowMajorMatrices = (ShaderCI.CompileFlags & SHADER_COMPILE_FLAG_PACK_MATRIX_ROW_MAJOR) != 0;
Attribs.pShaderSourceStreamFactory = ShaderCI.pShaderSourceStreamFactory;
Attribs.ppCompilerOutput = VkShaderCI.ppCompilerOutput;
Attribs.OptimizationLevel = ShaderCI.ShaderOptimizationLevel;

if (VkShaderCI.VkVersion >= VK_API_VERSION_1_2)
Attribs.Version = GLSLangUtils::SpirvVersion::Vk120;
Expand Down
1 change: 1 addition & 0 deletions Graphics/GraphicsTools/src/XXH128Hasher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ XXH128State& XXH128State::Update(const ShaderCreateInfo& ShaderCI) noexcept
ShaderCI.GLESSLVersion,
ShaderCI.MSLVersion,
ShaderCI.CompileFlags,
ShaderCI.ShaderOptimizationLevel,
ShaderCI.LoadConstantBufferReflection);

if (ShaderCI.Source != nullptr || ShaderCI.FilePath != nullptr)
Expand Down
3 changes: 2 additions & 1 deletion Graphics/ShaderTools/include/GLSLangUtils.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2019-2024 Diligent Graphics LLC
* Copyright 2019-2026 Diligent Graphics LLC
* Copyright 2015-2019 Egor Yusov
*
* Licensed under the Apache License, Version 2.0 (the "License");
Expand Down Expand Up @@ -64,6 +64,7 @@ struct GLSLtoSPIRVAttribs
IDataBlob** ppCompilerOutput = nullptr;
bool AssignBindings = true;
bool UseRowMajorMatrices = false;
SHADER_OPTIMIZATION_LEVEL OptimizationLevel = SHADER_OPTIMIZATION_LEVEL_DEFAULT;
};

std::vector<unsigned int> GLSLtoSPIRV(const GLSLtoSPIRVAttribs& Attribs);
Expand Down
48 changes: 35 additions & 13 deletions Graphics/ShaderTools/src/DXCompiler.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2019-2025 Diligent Graphics LLC
* Copyright 2019-2026 Diligent Graphics LLC
* Copyright 2015-2019 Egor Yusov
*
* Licensed under the Apache License, Version 2.0 (the "License");
Expand Down Expand Up @@ -691,6 +691,37 @@ void DXCompilerImpl::GetD3D12ShaderReflection(IDxcBlob* pShaderBy
}


static const wchar_t* GetDxcOptimizationArg(SHADER_OPTIMIZATION_LEVEL OptimizationLevel,
DXCompilerTarget Target,
const Version& DxcVersion)
{
switch (OptimizationLevel)
{
case SHADER_OPTIMIZATION_LEVEL_DISABLED:
return DXC_ARG_SKIP_OPTIMIZATIONS;
case SHADER_OPTIMIZATION_LEVEL_0:
return DXC_ARG_OPTIMIZATION_LEVEL0;
case SHADER_OPTIMIZATION_LEVEL_1:
return DXC_ARG_OPTIMIZATION_LEVEL1;
case SHADER_OPTIMIZATION_LEVEL_2:
return DXC_ARG_OPTIMIZATION_LEVEL2;
case SHADER_OPTIMIZATION_LEVEL_3:
return DXC_ARG_OPTIMIZATION_LEVEL3;
case SHADER_OPTIMIZATION_LEVEL_DEFAULT:
default:
// DEFAULT reproduces the historical behavior.
#ifdef DILIGENT_DEBUG
return DXC_ARG_SKIP_OPTIMIZATIONS;
#else
// For the Direct3D12 target, optimization was historically only enabled for DXC 1.5+.
if (Target == DXCompilerTarget::Direct3D12 && DxcVersion < Version{1, 5})
return DXC_ARG_SKIP_OPTIMIZATIONS;
return DXC_ARG_OPTIMIZATION_LEVEL3;
#endif
}
}


void DXCompilerImpl::Compile(const ShaderCreateInfo& ShaderCI,
ShaderVersion ShaderModel,
const char* Preamble,
Expand Down Expand Up @@ -733,33 +764,24 @@ void DXCompilerImpl::Compile(const ShaderCreateInfo& ShaderCI,
{
//DxilArgs.push_back(L"-WX"); // Warnings as errors
#ifdef DILIGENT_DEBUG
DxilArgs.push_back(DXC_ARG_DEBUG); // Debug info
DxilArgs.push_back(DXC_ARG_SKIP_OPTIMIZATIONS); // Disable optimization
DxilArgs.push_back(DXC_ARG_DEBUG); // Debug info
if (m_Library.GetVersion() >= Version{1, 5})
{
// Silence the following warning:
// no output provided for debug - embedding PDB in shader container. Use -Qembed_debug to silence this warning.
DxilArgs.push_back(L"-Qembed_debug");
}
#else
if (m_Library.GetVersion() >= Version{1, 5})
DxilArgs.push_back(DXC_ARG_OPTIMIZATION_LEVEL3); // Optimization level 3
else
DxilArgs.push_back(DXC_ARG_SKIP_OPTIMIZATIONS); // TODO: something goes wrong if optimization is enabled
#endif
DxilArgs.push_back(GetDxcOptimizationArg(ShaderCI.ShaderOptimizationLevel, m_Library.GetTarget(), m_Library.GetVersion()));
}
else if (m_Library.GetTarget() == DXCompilerTarget::Vulkan)
{
DxilArgs.assign(
{
L"-spirv",
L"-fspv-reflect",
#ifdef DILIGENT_DEBUG
DXC_ARG_SKIP_OPTIMIZATIONS,
#else
DXC_ARG_OPTIMIZATION_LEVEL3
#endif
});
DxilArgs.push_back(GetDxcOptimizationArg(ShaderCI.ShaderOptimizationLevel, m_Library.GetTarget(), m_Library.GetVersion()));

if (m_APIVersion >= VK_API_VERSION_1_2 && ShaderModel >= ShaderVersion{6, 3})
{
Expand Down
37 changes: 27 additions & 10 deletions Graphics/ShaderTools/src/GLSLangUtils.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2019-2025 Diligent Graphics LLC
* Copyright 2019-2026 Diligent Graphics LLC
* Copyright 2015-2019 Egor Yusov
*
* Licensed under the Apache License, Version 2.0 (the "License");
Expand Down Expand Up @@ -427,6 +427,17 @@ spv_target_env SpirvVersionToSpvTargetEnv(SpirvVersion Version)

} // namespace

#ifdef USE_SPIRV_TOOLS
static SPIRV_OPTIMIZATION_FLAGS GetSpirvPerformanceFlag(SHADER_OPTIMIZATION_LEVEL OptimizationLevel)
{
// SPIRV-Tools has no O0-O3 granularity. DEFAULT and explicit levels 0..3 enable the
// performance pass; only DISABLED skips it. (Legalization, when required, is applied separately.)
return OptimizationLevel == SHADER_OPTIMIZATION_LEVEL_DISABLED ?
SPIRV_OPTIMIZATION_FLAG_NONE :
SPIRV_OPTIMIZATION_FLAG_PERFORMANCE;
}
#endif

std::vector<unsigned int> HLSLtoSPIRV(const ShaderCreateInfo& ShaderCI,
SpirvVersion Version,
const char* ExtraDefinitions,
Expand Down Expand Up @@ -487,8 +498,10 @@ std::vector<unsigned int> HLSLtoSPIRV(const ShaderCreateInfo& ShaderCI,

#ifdef USE_SPIRV_TOOLS
// SPIR-V bytecode generated from HLSL must be legalized to
// turn it into a valid vulkan SPIR-V shader.
std::vector<uint32_t> LegalizedSPIRV = OptimizeSPIRV(SPIRV, SpirvVersionToSpvTargetEnv(Version), SPIRV_OPTIMIZATION_FLAG_LEGALIZATION | SPIRV_OPTIMIZATION_FLAG_PERFORMANCE);
// turn it into a valid vulkan SPIR-V shader. Legalization is always applied for correctness;
// the performance pass is gated by the shader optimization level.
const SPIRV_OPTIMIZATION_FLAGS OptimizationFlags = SPIRV_OPTIMIZATION_FLAG_LEGALIZATION | GetSpirvPerformanceFlag(ShaderCI.ShaderOptimizationLevel);
std::vector<uint32_t> LegalizedSPIRV = OptimizeSPIRV(SPIRV, SpirvVersionToSpvTargetEnv(Version), OptimizationFlags);
if (!LegalizedSPIRV.empty())
{
return LegalizedSPIRV;
Expand Down Expand Up @@ -535,14 +548,18 @@ std::vector<unsigned int> GLSLtoSPIRV(const GLSLtoSPIRVAttribs& Attribs)
return SPIRV;

#ifdef USE_SPIRV_TOOLS
std::vector<uint32_t> OptimizedSPIRV = OptimizeSPIRV(SPIRV, SpirvVersionToSpvTargetEnv(Attribs.Version), SPIRV_OPTIMIZATION_FLAG_PERFORMANCE);
if (!OptimizedSPIRV.empty())
{
return OptimizedSPIRV;
}
else
const SPIRV_OPTIMIZATION_FLAGS OptimizationFlags = GetSpirvPerformanceFlag(Attribs.OptimizationLevel);
if (OptimizationFlags != SPIRV_OPTIMIZATION_FLAG_NONE)
{
LOG_ERROR("Failed to optimize SPIR-V.");
std::vector<uint32_t> OptimizedSPIRV = OptimizeSPIRV(SPIRV, SpirvVersionToSpvTargetEnv(Attribs.Version), OptimizationFlags);
if (!OptimizedSPIRV.empty())
{
return OptimizedSPIRV;
}
else
{
LOG_ERROR("Failed to optimize SPIR-V.");
}
}
#endif
return SPIRV;
Expand Down
1 change: 1 addition & 0 deletions ReleaseHistory.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

## Current progress

* Added `SHADER_OPTIMIZATION_LEVEL` enum and `ShaderCreateInfo::ShaderOptimizationLevel` member (API256018)
* Added `DrawMeshIndirectAttribs::pMtlAttribs` member (API256017)
* `DrawMeshIndirectAttribs::pMtlAttribs` allows specifying Metal object and mesh thread group sizes for `IDeviceContext::DrawMeshIndirect()`
* Added `DrawMeshAttribsMtl` struct and `DrawMeshAttribs::pMtlAttribs` member (API256016)
Expand Down
3 changes: 2 additions & 1 deletion Tests/DiligentCoreTest/src/Common/HashUtilsTest.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2019-2024 Diligent Graphics LLC
* Copyright 2019-2026 Diligent Graphics LLC
* Copyright 2015-2019 Egor Yusov
*
* Licensed under the Apache License, Version 2.0 (the "License");
Expand Down Expand Up @@ -1185,6 +1185,7 @@ TEST(XXH128HasherTest, ShaderCreateInfo)
TEST_RANGE(MSLVersion.Major, 1u, 10u);

TEST_FLAGS(CompileFlags, static_cast<SHADER_COMPILE_FLAGS>(1), SHADER_COMPILE_FLAG_LAST);
TEST_RANGE(ShaderOptimizationLevel, static_cast<SHADER_OPTIMIZATION_LEVEL>(1), SHADER_OPTIMIZATION_LEVEL_COUNT);
TEST_BOOL(LoadConstantBufferReflection);

TEST_STRINGS(GLSLExtensions, "Extension 1", "Extension 2", "Extension 3");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -789,6 +789,7 @@ void SerializeShaderCreateInfo(bool UseBytecode)
RefCI.GLESSLVersion = {5, 6};
RefCI.MSLVersion = {7, 8};
RefCI.CompileFlags = SHADER_COMPILE_FLAG_SKIP_REFLECTION;
RefCI.ShaderOptimizationLevel = SHADER_OPTIMIZATION_LEVEL_3;
RefCI.LoadConstantBufferReflection = true;
RefCI.GLSLExtensions = "My extension";
RefCI.WebGPUEmulatedArrayIndexSuffix = "My suffix";
Expand Down Expand Up @@ -839,6 +840,7 @@ void SerializeShaderCreateInfo(bool UseBytecode)
EXPECT_EQ (CI.GLESSLVersion, RefCI.GLESSLVersion);
EXPECT_EQ (CI.MSLVersion, RefCI.MSLVersion);
EXPECT_EQ (CI.CompileFlags, RefCI.CompileFlags);
EXPECT_EQ (CI.ShaderOptimizationLevel, RefCI.ShaderOptimizationLevel);
EXPECT_EQ (CI.LoadConstantBufferReflection, RefCI.LoadConstantBufferReflection);
EXPECT_STREQ(CI.GLSLExtensions, RefCI.GLSLExtensions);
EXPECT_STREQ(CI.WebGPUEmulatedArrayIndexSuffix, RefCI.WebGPUEmulatedArrayIndexSuffix);
Expand Down
Loading