Skip to content

Commit 5443eb7

Browse files
Add SHADER_VARIABLE_FLAG_INLINE_CONSTANTS flag with implementation in D3D12 (#672)
1 parent 4bdeda4 commit 5443eb7

File tree

4 files changed

+155
-6
lines changed

4 files changed

+155
-6
lines changed

Graphics/GraphicsAccessories/src/GraphicsAccessories.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1843,7 +1843,7 @@ PIPELINE_RESOURCE_FLAGS GetValidPipelineResourceFlags(SHADER_RESOURCE_TYPE Resou
18431843

18441844
PIPELINE_RESOURCE_FLAGS ShaderVariableFlagsToPipelineResourceFlags(SHADER_VARIABLE_FLAGS Flags)
18451845
{
1846-
static_assert(SHADER_VARIABLE_FLAG_LAST == (1 << 3), "Please update the switch below to handle the new shader variable flags");
1846+
static_assert(SHADER_VARIABLE_FLAG_LAST == (1 << 4), "Please update the switch below to handle the new shader variable flags");
18471847
switch (Flags)
18481848
{
18491849
case SHADER_VARIABLE_FLAG_NONE:
@@ -1859,6 +1859,9 @@ PIPELINE_RESOURCE_FLAGS ShaderVariableFlagsToPipelineResourceFlags(SHADER_VARIAB
18591859
case SHADER_VARIABLE_FLAG_NON_FILTERING_SAMPLER_WEBGPU:
18601860
return PIPELINE_RESOURCE_FLAG_NONE;
18611861

1862+
case SHADER_VARIABLE_FLAG_INLINE_CONSTANTS:
1863+
return PIPELINE_RESOURCE_FLAG_INLINE_CONSTANTS;
1864+
18621865
default:
18631866
UNEXPECTED("Unexpected shader variable flag");
18641867
return PIPELINE_RESOURCE_FLAG_NONE;

Graphics/GraphicsEngine/interface/PipelineState.h

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -103,22 +103,30 @@ DILIGENT_TYPED_ENUM(SHADER_VARIABLE_FLAGS, Uint8)
103103
/// flag in the internal pipeline resource signature.
104104
SHADER_VARIABLE_FLAG_NO_DYNAMIC_BUFFERS = 1u << 0,
105105

106+
/// Indicates that the resource consists of inline constants
107+
/// (also known as push constants in Vulkan or root constants in Direct3D12).
108+
/// Applies to Diligent::SHADER_RESOURCE_TYPE_CONSTANT_BUFFER only.
109+
///
110+
/// \remarks This flag directly translates to the Diligent::PIPELINE_RESOURCE_FLAG_INLINE_CONSTANTS
111+
/// flag in the internal pipeline resource signature.
112+
SHADER_VARIABLE_FLAG_INLINE_CONSTANTS = 1u << 1,
113+
106114
/// Indicates that the resource is an input attachment in general layout, which allows simultaneously
107115
/// reading from the resource through the input attachment and writing to it via color or depth-stencil
108116
/// attachment.
109117
///
110118
/// \note This flag is only valid in Vulkan.
111-
SHADER_VARIABLE_FLAG_GENERAL_INPUT_ATTACHMENT_VK = 1u << 1,
119+
SHADER_VARIABLE_FLAG_GENERAL_INPUT_ATTACHMENT_VK = 1u << 2,
112120

113121
/// Indicates that the resource is an unfilterable-float texture.
114122
///
115123
/// \note This flag is only valid in WebGPU and ignored in other backends.
116-
SHADER_VARIABLE_FLAG_UNFILTERABLE_FLOAT_TEXTURE_WEBGPU = 1u << 2,
124+
SHADER_VARIABLE_FLAG_UNFILTERABLE_FLOAT_TEXTURE_WEBGPU = 1u << 3,
117125

118126
/// Indicates that the resource is a non-filtering sampler.
119127
///
120128
/// \note This flag is only valid in WebGPU and ignored in other backends.
121-
SHADER_VARIABLE_FLAG_NON_FILTERING_SAMPLER_WEBGPU = 1u << 3,
129+
SHADER_VARIABLE_FLAG_NON_FILTERING_SAMPLER_WEBGPU = 1u << 4,
122130

123131
/// Special value that indicates the last flag in the enumeration.
124132
SHADER_VARIABLE_FLAG_LAST = SHADER_VARIABLE_FLAG_NON_FILTERING_SAMPLER_WEBGPU

Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2019-2024 Diligent Graphics LLC
2+
* Copyright 2019-2025 Diligent Graphics LLC
33
* Copyright 2015-2019 Egor Yusov
44
*
55
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -380,7 +380,26 @@ PipelineResourceSignatureDescWrapper PipelineStateD3D12Impl::GetDefaultResourceS
380380

381381
const SHADER_RESOURCE_TYPE ResType = Attribs.GetShaderResourceType();
382382
const PIPELINE_RESOURCE_FLAGS ResFlags = Attribs.GetPipelineResourceFlags() | ShaderVariableFlagsToPipelineResourceFlags(VarDesc.Flags);
383-
SignDesc.AddResource(VarDesc.ShaderStages, Attribs.Name, Attribs.BindCount, ResType, VarDesc.Type, ResFlags);
383+
384+
Uint32 ArraySize = Attribs.BindCount;
385+
if (ResFlags & PIPELINE_RESOURCE_FLAG_INLINE_CONSTANTS)
386+
{
387+
VERIFY_EXPR(ResType == SHADER_RESOURCE_TYPE_CONSTANT_BUFFER);
388+
VERIFY(ResFlags == PIPELINE_RESOURCE_FLAG_INLINE_CONSTANTS, "INLINE_CONSTANTS flag cannot be combined with other flags.");
389+
if (Attribs.BindCount != 1)
390+
{
391+
LOG_ERROR_AND_THROW("Inline constants resource '", Attribs.Name, "' in shader '", pShader->GetDesc().Name,
392+
"' can not be an array.");
393+
}
394+
const Uint32 NumConstants = Attribs.GetConstantBufferSize() / sizeof(Uint32);
395+
if (NumConstants > 64)
396+
{
397+
LOG_ERROR_AND_THROW("Inline constants resource '", Attribs.Name, "' in shader '", pShader->GetDesc().Name,
398+
"' has ", NumConstants, " constants. The maximum supported number of inline constants is 64.");
399+
}
400+
ArraySize = NumConstants;
401+
}
402+
SignDesc.AddResource(VarDesc.ShaderStages, Attribs.Name, ArraySize, ResType, VarDesc.Type, ResFlags);
384403
}
385404
else
386405
{

Tests/DiligentCoreAPITest/src/InlineConstantsTest.cpp

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,125 @@ InlineConstants::Resources InlineConstants::sm_Res;
165165
FastRandFloat InlineConstants::sm_Rnd{0, 0.f, 1.f};
166166

167167

168+
TEST_F(InlineConstants, ResourceLayout)
169+
{
170+
GPUTestingEnvironment* pEnv = GPUTestingEnvironment::GetInstance();
171+
IRenderDevice* pDevice = pEnv->GetDevice();
172+
IDeviceContext* pContext = pEnv->GetDeviceContext();
173+
ISwapChain* pSwapChain = pEnv->GetSwapChain();
174+
if (pDevice->GetDeviceInfo().Type != RENDER_DEVICE_TYPE_D3D12)
175+
{
176+
GTEST_SKIP();
177+
}
178+
179+
for (Uint32 pos_type = 0; pos_type < SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES; ++pos_type)
180+
{
181+
for (Uint32 col_type = 0; col_type < SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES; ++col_type)
182+
{
183+
const float ClearColor[] = {sm_Rnd(), sm_Rnd(), sm_Rnd(), sm_Rnd()};
184+
RenderDrawCommandReference(pSwapChain, ClearColor);
185+
186+
SHADER_RESOURCE_VARIABLE_TYPE PosType = static_cast<SHADER_RESOURCE_VARIABLE_TYPE>(pos_type);
187+
SHADER_RESOURCE_VARIABLE_TYPE ColType = static_cast<SHADER_RESOURCE_VARIABLE_TYPE>(col_type);
188+
189+
GraphicsPipelineStateCreateInfoX PsoCI{"Inline constants test"};
190+
191+
PipelineResourceLayoutDescX ResLayoutDesc;
192+
ResLayoutDesc
193+
.AddVariable(SHADER_TYPE_VERTEX, "cbInlinePositions", PosType, SHADER_VARIABLE_FLAG_INLINE_CONSTANTS)
194+
.AddVariable(SHADER_TYPE_VERTEX, "cbInlineColors", ColType, SHADER_VARIABLE_FLAG_INLINE_CONSTANTS);
195+
196+
PsoCI
197+
.AddRenderTarget(pSwapChain->GetDesc().ColorBufferFormat)
198+
.SetPrimitiveTopology(PRIMITIVE_TOPOLOGY_TRIANGLE_LIST)
199+
.AddShader(sm_Res.pVS)
200+
.AddShader(sm_Res.pPS)
201+
.SetResourceLayout(ResLayoutDesc);
202+
PsoCI.GraphicsPipeline.DepthStencilDesc.DepthEnable = False;
203+
204+
RefCntAutoPtr<IPipelineState> pPSO;
205+
pDevice->CreateGraphicsPipelineState(PsoCI, &pPSO);
206+
ASSERT_TRUE(pPSO);
207+
208+
if (PosType == SHADER_RESOURCE_VARIABLE_TYPE_STATIC)
209+
{
210+
IShaderResourceVariable* pVar = pPSO->GetStaticVariableByName(SHADER_TYPE_VERTEX, "cbInlinePositions");
211+
ASSERT_TRUE(pVar);
212+
pVar->SetInlineConstants(g_Positions, 0, kNumPosConstants);
213+
}
214+
215+
if (ColType == SHADER_RESOURCE_VARIABLE_TYPE_STATIC)
216+
{
217+
IShaderResourceVariable* pVar = pPSO->GetStaticVariableByName(SHADER_TYPE_VERTEX, "cbInlineColors");
218+
ASSERT_TRUE(pVar);
219+
pVar->SetInlineConstants(g_Colors, 0, kNumColConstants);
220+
}
221+
222+
RefCntAutoPtr<IShaderResourceBinding> pSRB;
223+
pPSO->CreateShaderResourceBinding(&pSRB, true);
224+
ASSERT_TRUE(pSRB);
225+
226+
IShaderResourceVariable* pPosVar = nullptr;
227+
if (PosType != SHADER_RESOURCE_VARIABLE_TYPE_STATIC)
228+
{
229+
pPosVar = pSRB->GetVariableByName(SHADER_TYPE_VERTEX, "cbInlinePositions");
230+
ASSERT_TRUE(pPosVar);
231+
}
232+
233+
IShaderResourceVariable* pColVar = nullptr;
234+
if (ColType != SHADER_RESOURCE_VARIABLE_TYPE_STATIC)
235+
{
236+
pColVar = pSRB->GetVariableByName(SHADER_TYPE_VERTEX, "cbInlineColors");
237+
ASSERT_TRUE(pColVar);
238+
}
239+
240+
ITextureView* pRTVs[] = {pSwapChain->GetCurrentBackBufferRTV()};
241+
pContext->SetRenderTargets(1, pRTVs, nullptr, RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
242+
pContext->ClearRenderTarget(pRTVs[0], ClearColor, RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
243+
244+
245+
if (pColVar != nullptr)
246+
{
247+
// Set first half of color constants before committing SRB
248+
pColVar->SetInlineConstants(g_Colors, 0, kNumColConstants / 2);
249+
}
250+
251+
pContext->CommitShaderResources(pSRB, RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
252+
253+
if (pColVar != nullptr)
254+
{
255+
// Set second half of color constants after committing SRB
256+
pColVar->SetInlineConstants(g_Colors[0].Data() + kNumColConstants / 2, kNumColConstants / 2, kNumColConstants / 2);
257+
}
258+
259+
pContext->SetPipelineState(pPSO);
260+
261+
if (pPosVar == nullptr)
262+
{
263+
// Draw both triangles as positions are static
264+
pContext->Draw({6, DRAW_FLAG_VERIFY_ALL});
265+
}
266+
else
267+
{
268+
// Draw first triangle
269+
pPosVar->SetInlineConstants(g_Positions, 0, kNumPosConstants / 2);
270+
pContext->Draw({3, DRAW_FLAG_VERIFY_ALL});
271+
272+
// Draw second triangle
273+
pPosVar->SetInlineConstants(g_Positions[0].Data() + kNumPosConstants / 2, 0, kNumPosConstants / 2);
274+
pContext->Draw({3, DRAW_FLAG_VERIFY_ALL});
275+
}
276+
277+
Present();
278+
279+
std::cout << TestingEnvironment::GetCurrentTestStatusString() << ' '
280+
<< " Pos " << GetShaderVariableTypeLiteralName(PosType) << ','
281+
<< " Col " << GetShaderVariableTypeLiteralName(ColType) << std::endl;
282+
}
283+
}
284+
}
285+
286+
168287
void InlineConstants::TestSignatures(Uint32 NumSignatures)
169288
{
170289
GPUTestingEnvironment* pEnv = GPUTestingEnvironment::GetInstance();

0 commit comments

Comments
 (0)