@@ -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