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");
2929
3030#include " gtest/gtest.h"
3131
32+ #include " InlineShaders/DrawCommandTestHLSL.h"
33+
3234using namespace Diligent ;
3335using namespace Diligent ::Testing;
3436
37+ namespace Diligent
38+ {
39+ namespace Testing
40+ {
41+ void RenderDrawCommandReference (ISwapChain* pSwapChain, const float * pClearColor);
42+ }
43+ } // namespace Diligent
44+
3545namespace
3646{
3747
3848TEST (ShaderResourceLayout, ResourceArray)
3949{
40- auto * pEnv = GPUTestingEnvironment::GetInstance ();
41- auto * pDevice = pEnv->GetDevice ();
42- auto * pContext = pEnv->GetDeviceContext ();
50+ GPUTestingEnvironment * pEnv = GPUTestingEnvironment::GetInstance ();
51+ IRenderDevice* pDevice = pEnv->GetDevice ();
52+ IDeviceContext* pContext = pEnv->GetDeviceContext ();
4353
4454 GPUTestingEnvironment::ScopedReset EnvironmentAutoReset;
4555
@@ -155,12 +165,12 @@ TEST(ShaderResourceLayout, ResourceArray)
155165
156166 RefCntAutoPtr<ITextureView> pRTV, pDSV;
157167 {
158- auto pRenderTarget = pEnv->CreateTexture (" ShaderResourceLayout: offscreen render target" , TEX_FORMAT_RGBA8_UNORM, BIND_RENDER_TARGET, 256 , 256 );
168+ RefCntAutoPtr<ITexture> pRenderTarget = pEnv->CreateTexture (" ShaderResourceLayout: offscreen render target" , TEX_FORMAT_RGBA8_UNORM, BIND_RENDER_TARGET, 256 , 256 );
159169 ASSERT_NE (pRenderTarget, nullptr );
160170 pRTV = pRenderTarget->GetDefaultView (TEXTURE_VIEW_RENDER_TARGET);
161171 ASSERT_NE (pRTV, nullptr );
162172
163- auto pDepth = pEnv->CreateTexture (" ShaderResourceLayout: offscreen depth" , TEX_FORMAT_D32_FLOAT, BIND_DEPTH_STENCIL, 256 , 256 );
173+ RefCntAutoPtr<ITexture> pDepth = pEnv->CreateTexture (" ShaderResourceLayout: offscreen depth" , TEX_FORMAT_D32_FLOAT, BIND_DEPTH_STENCIL, 256 , 256 );
164174 ASSERT_NE (pDepth, nullptr );
165175 pDSV = pDepth->GetDefaultView (TEXTURE_VIEW_DEPTH_STENCIL);
166176 ASSERT_NE (pDSV, nullptr );
@@ -186,7 +196,7 @@ TEST(ShaderResourceLayout, ResourceArray)
186196 std::vector<TextureSubResData> SubResources (TexDesc.MipLevels );
187197 for (Uint32 i = 0 ; i < TexDesc.MipLevels ; ++i)
188198 {
189- auto & SubResData = SubResources[i];
199+ TextureSubResData & SubResData{ SubResources[i]} ;
190200 SubResData.pData = Data.data ();
191201 SubResData.Stride = TexDesc.Width * 4 ;
192202 }
@@ -262,4 +272,129 @@ TEST(ShaderResourceLayout, ResourceArray)
262272 pContext->Draw (DrawAttrs);
263273}
264274
275+ namespace HLSL
276+ {
277+ const std::string DynamicArrayIndexingPS{R"(
278+ struct PSInput
279+ {
280+ float4 Pos : SV_POSITION;
281+ float3 Color : COLOR;
282+ };
283+
284+ SamplerState g_Sampler;
285+ Texture2D<float4> g_Textures[4];
286+
287+ cbuffer cbConstants
288+ {
289+ uint g_TextureIndex;
290+ }
291+
292+ float4 main(in PSInput PSIn) : SV_Target
293+ {
294+ float3 Color = PSIn.Color.rgb;
295+ Color *= g_Textures[g_TextureIndex].Sample(g_Sampler, float2(0.5, 0.5)).rgb;
296+ return float4(Color.rgb, 1.0);
297+ }
298+ )" };
299+ }
300+
301+ TEST (ShaderResourceArrayTest, DynamicArrayIndexing)
302+ {
303+ GPUTestingEnvironment* pEnv = GPUTestingEnvironment::GetInstance ();
304+ IRenderDevice* pDevice = pEnv->GetDevice ();
305+ IDeviceContext* pContext = pEnv->GetDeviceContext ();
306+ const RenderDeviceInfo& DeviceInfo = pDevice->GetDeviceInfo ();
307+
308+ if (!(DeviceInfo.Type == RENDER_DEVICE_TYPE_D3D12 || DeviceInfo.Type == RENDER_DEVICE_TYPE_VULKAN))
309+ {
310+ GTEST_SKIP () << " Dynamic array indexing is not supported on this device" ;
311+ }
312+
313+ GPUTestingEnvironment::ScopedReset EnvironmentAutoReset;
314+
315+ ISwapChain* pSwapChain = pEnv->GetSwapChain ();
316+ const SwapChainDesc& SCDesc = pSwapChain->GetDesc ();
317+
318+ float ClearColor[] = {0.875 , 0.125 , 0.75 , 0.25 };
319+ RenderDrawCommandReference (pSwapChain, ClearColor);
320+
321+ ShaderCreateInfo ShaderCI;
322+ ShaderCI.HLSLVersion = ShaderVersion{5 , 1 };
323+
324+ RefCntAutoPtr<IShader> pVS, pPS;
325+ {
326+ ShaderCI.Desc = {" ShaderResourceArrayTest.DynamicArrayIndexing: VS" , SHADER_TYPE_VERTEX, false };
327+ ShaderCI.EntryPoint = " main" ;
328+ ShaderCI.Source = HLSL::DrawTest_ProceduralTriangleVS.c_str ();
329+ ShaderCI.SourceLanguage = SHADER_SOURCE_LANGUAGE_HLSL;
330+ pDevice->CreateShader (ShaderCI, &pVS);
331+ ASSERT_NE (pVS, nullptr );
332+ }
333+
334+ {
335+ ShaderCI.Desc = {" ShaderResourceArrayTest.DynamicArrayIndexing: PS" , SHADER_TYPE_PIXEL, false };
336+ ShaderCI.Source = HLSL::DynamicArrayIndexingPS.c_str ();
337+ ShaderCI.SourceLanguage = SHADER_SOURCE_LANGUAGE_HLSL;
338+ pDevice->CreateShader (ShaderCI, &pPS);
339+ ASSERT_NE (pPS, nullptr );
340+ }
341+
342+ GraphicsPipelineStateCreateInfo PSOCreateInfo;
343+ PipelineStateDesc& PSODesc = PSOCreateInfo.PSODesc ;
344+ GraphicsPipelineDesc& GraphicsPipeline = PSOCreateInfo.GraphicsPipeline ;
345+
346+ PSODesc.Name = " ShaderResourceArrayTest.DynamicArrayIndexing" ;
347+
348+ PSODesc.ResourceLayout .DefaultVariableType = SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE;
349+ ImmutableSamplerDesc ImtblSampler{SHADER_TYPE_PIXEL, " g_Sampler" , SamplerDesc{}};
350+ PSODesc.ResourceLayout .ImmutableSamplers = &ImtblSampler;
351+ PSODesc.ResourceLayout .NumImmutableSamplers = 1 ;
352+
353+ GraphicsPipeline.DepthStencilDesc .DepthEnable = False;
354+ GraphicsPipeline.RasterizerDesc .CullMode = CULL_MODE_NONE;
355+ GraphicsPipeline.NumRenderTargets = 1 ;
356+ GraphicsPipeline.RTVFormats [0 ] = SCDesc.ColorBufferFormat ;
357+ PSOCreateInfo.pVS = pVS;
358+ PSOCreateInfo.pPS = pPS;
359+
360+ RefCntAutoPtr<IPipelineState> pPSO;
361+ pDevice->CreateGraphicsPipelineState (PSOCreateInfo, &pPSO);
362+ ASSERT_NE (pPSO, nullptr );
363+
364+ RefCntAutoPtr<IShaderResourceBinding> pSRB;
365+ pPSO->CreateShaderResourceBinding (&pSRB);
366+ ASSERT_NE (pSRB, nullptr );
367+
368+ std::vector<Uint32> BufferData{{2 , 0 , 0 , 0 }};
369+ RefCntAutoPtr<IBuffer> pBuffer = pEnv->CreateBuffer (BufferDesc{" ShaderResourceArrayTest.DynamicArrayIndexing" , BufferData.size (), BIND_UNIFORM_BUFFER, USAGE_DEFAULT}, BufferData.data ());
370+ ASSERT_NE (pBuffer, nullptr );
371+ pSRB->GetVariableByName (SHADER_TYPE_PIXEL, " cbConstants" )->Set (pBuffer);
372+
373+ std::vector<Uint32> BlackTextData (64 * 64 , 0 );
374+ std::vector<Uint32> WhiteTextData (64 * 64 , ~0u );
375+ RefCntAutoPtr<ITexture> pBlackTex = pEnv->CreateTexture (" Black texture" , TEX_FORMAT_RGBA8_UNORM, BIND_SHADER_RESOURCE, 64 , 64 , BlackTextData.data ());
376+ RefCntAutoPtr<ITexture> pWhiteTex = pEnv->CreateTexture (" White texture" , TEX_FORMAT_RGBA8_UNORM, BIND_SHADER_RESOURCE, 64 , 64 , WhiteTextData.data ());
377+ ASSERT_NE (pBlackTex, nullptr );
378+ ASSERT_NE (pWhiteTex, nullptr );
379+ ITextureView* pWhiteTexSRV = pWhiteTex->GetDefaultView (TEXTURE_VIEW_SHADER_RESOURCE);
380+ ITextureView* pBlackTexSRV = pBlackTex->GetDefaultView (TEXTURE_VIEW_SHADER_RESOURCE);
381+ ASSERT_NE (pWhiteTexSRV, nullptr );
382+ ASSERT_NE (pBlackTexSRV, nullptr );
383+
384+ IDeviceObject* pTextures[] = {pBlackTexSRV, pBlackTexSRV, pWhiteTexSRV, pBlackTexSRV};
385+ pSRB->GetVariableByName (SHADER_TYPE_PIXEL, " g_Textures" )->SetArray (pTextures, 0 , _countof (pTextures));
386+
387+ ITextureView* ppRTVs[] = {pSwapChain->GetCurrentBackBufferRTV ()};
388+ pContext->SetRenderTargets (1 , ppRTVs, nullptr , RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
389+ pContext->ClearRenderTarget (ppRTVs[0 ], ClearColor, RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
390+
391+ pContext->SetPipelineState (pPSO);
392+ pContext->CommitShaderResources (pSRB, RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
393+
394+ DrawAttribs DrawAttrs{6 , DRAW_FLAG_VERIFY_ALL};
395+ pContext->Draw (DrawAttrs);
396+
397+ pSwapChain->Present ();
398+ }
399+
265400} // namespace
0 commit comments