Skip to content

Commit 759dacb

Browse files
hzqstTheMostDiligent
authored andcommitted
Add tests for specialization constants
1 parent 955da29 commit 759dacb

2 files changed

Lines changed: 507 additions & 0 deletions

File tree

Tests/DiligentCoreAPITest/src/ObjectCreationFailure/PSOCreationFailureTest.cpp

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1759,4 +1759,128 @@ TEST_F(PSOCreationFailureTest, SpecConst_ErrorAtSecondElement)
17591759
}
17601760

17611761

1762+
// ---------------------------------------------------------------------------
1763+
// Vulkan-specific tests for BuildSpecializationData (Name->SpecId matching).
1764+
// These require GLSL shaders with layout(constant_id) declarations so that
1765+
// the reflected specialization constants are available for matching.
1766+
// ---------------------------------------------------------------------------
1767+
1768+
// Providing a user constant whose name does not match any reflected constant
1769+
// in the shader should succeed silently (the constant is simply skipped).
1770+
TEST_F(PSOCreationFailureTest, SpecConst_UnmatchedNameIsSkipped)
1771+
{
1772+
auto* const pEnv = GPUTestingEnvironment::GetInstance();
1773+
auto* const pDevice = pEnv->GetDevice();
1774+
const auto& DeviceInfo = pDevice->GetDeviceInfo();
1775+
1776+
if (!DeviceInfo.IsVulkanDevice())
1777+
GTEST_SKIP() << "Name->SpecId matching is currently Vulkan-only";
1778+
if (DeviceInfo.Features.SpecializationConstants != DEVICE_FEATURE_STATE_ENABLED)
1779+
GTEST_SKIP() << "Specialization constants are not supported by this device";
1780+
1781+
// GLSL vertex shader with one specialization constant named "sc_Scale".
1782+
static constexpr char VSSource_GLSL[] = R"(
1783+
#version 450
1784+
layout(constant_id = 0) const float sc_Scale = 1.0;
1785+
#ifndef GL_ES
1786+
out gl_PerVertex { vec4 gl_Position; };
1787+
#endif
1788+
void main()
1789+
{
1790+
gl_Position = vec4(0.0, 0.0, 0.0, sc_Scale);
1791+
}
1792+
)";
1793+
1794+
static constexpr char PSSource_GLSL[] = R"(
1795+
#version 450
1796+
layout(location = 0) out vec4 out_Color;
1797+
void main()
1798+
{
1799+
out_Color = vec4(0.0, 0.0, 0.0, 1.0);
1800+
}
1801+
)";
1802+
1803+
ShaderCreateInfo ShaderCI;
1804+
ShaderCI.SourceLanguage = SHADER_SOURCE_LANGUAGE_GLSL_VERBATIM;
1805+
1806+
RefCntAutoPtr<IShader> pVS;
1807+
{
1808+
ShaderCI.Desc = {"SpecConst UnmatchedName VS", SHADER_TYPE_VERTEX, true};
1809+
ShaderCI.Source = VSSource_GLSL;
1810+
pDevice->CreateShader(ShaderCI, &pVS);
1811+
ASSERT_TRUE(pVS);
1812+
}
1813+
1814+
RefCntAutoPtr<IShader> pPS;
1815+
{
1816+
ShaderCI.Desc = {"SpecConst UnmatchedName PS", SHADER_TYPE_PIXEL, true};
1817+
ShaderCI.Source = PSSource_GLSL;
1818+
pDevice->CreateShader(ShaderCI, &pPS);
1819+
ASSERT_TRUE(pPS);
1820+
}
1821+
1822+
const float Data = 2.0f;
1823+
SpecializationConstant SpecConsts[] = {
1824+
// This name does not exist in the shader; it should be silently skipped.
1825+
{"sc_NonExistent", SHADER_TYPE_VERTEX, sizeof(Data), &Data},
1826+
};
1827+
1828+
auto PsoCI{GetGraphicsPSOCreateInfo("SpecConst UnmatchedNameIsSkipped")};
1829+
PsoCI.pVS = pVS;
1830+
PsoCI.pPS = pPS;
1831+
PsoCI.NumSpecializationConstants = _countof(SpecConsts);
1832+
PsoCI.pSpecializationConstants = SpecConsts;
1833+
1834+
RefCntAutoPtr<IPipelineState> pPSO;
1835+
pDevice->CreateGraphicsPipelineState(PsoCI, &pPSO);
1836+
EXPECT_NE(pPSO, nullptr) << "Unmatched specialization constant name should be silently skipped";
1837+
}
1838+
1839+
TEST_F(PSOCreationFailureTest, SpecConst_InsufficientData)
1840+
{
1841+
auto* const pEnv = GPUTestingEnvironment::GetInstance();
1842+
auto* const pDevice = pEnv->GetDevice();
1843+
const auto& DeviceInfo = pDevice->GetDeviceInfo();
1844+
1845+
if (!DeviceInfo.IsVulkanDevice())
1846+
GTEST_SKIP() << "Name->SpecId matching is currently Vulkan-only";
1847+
if (DeviceInfo.Features.SpecializationConstants != DEVICE_FEATURE_STATE_ENABLED)
1848+
GTEST_SKIP() << "Specialization constants are not supported by this device";
1849+
1850+
// GLSL compute shader with a float specialization constant (4 bytes).
1851+
// The spec constant must be used so the compiler does not optimize it away.
1852+
static constexpr char CSSource_GLSL[] = R"(
1853+
#version 450
1854+
layout(constant_id = 0) const float sc_Value = 1.0;
1855+
layout(rgba8, binding = 0) writeonly uniform image2D g_DummyUAV;
1856+
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
1857+
void main()
1858+
{
1859+
imageStore(g_DummyUAV, ivec2(0), vec4(sc_Value));
1860+
}
1861+
)";
1862+
1863+
ShaderCreateInfo ShaderCI;
1864+
ShaderCI.SourceLanguage = SHADER_SOURCE_LANGUAGE_GLSL_VERBATIM;
1865+
ShaderCI.Desc = {"SpecConst InsufficientData CS", SHADER_TYPE_COMPUTE, true};
1866+
ShaderCI.Source = CSSource_GLSL;
1867+
1868+
RefCntAutoPtr<IShader> pCS;
1869+
pDevice->CreateShader(ShaderCI, &pCS);
1870+
ASSERT_TRUE(pCS);
1871+
1872+
// Provide 2 bytes for a 4-byte float constant (insufficient).
1873+
const Uint16 SmallData = 0;
1874+
SpecializationConstant SpecConsts[] = {
1875+
{"sc_Value", SHADER_TYPE_COMPUTE, sizeof(SmallData), &SmallData},
1876+
};
1877+
1878+
auto PsoCI{GetComputePSOCreateInfo("PSO Create Failure - SpecConst InsufficientData")};
1879+
PsoCI.pCS = pCS;
1880+
PsoCI.NumSpecializationConstants = _countof(SpecConsts);
1881+
PsoCI.pSpecializationConstants = SpecConsts;
1882+
TestCreatePSOFailure(PsoCI, "insufficient data");
1883+
}
1884+
1885+
17621886
} // namespace

0 commit comments

Comments
 (0)