ShaderResourceGroupPool.cpp 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include <Atom/RHI/DeviceBufferView.h>
  9. #include <Atom/RHI/Factory.h>
  10. #include <Atom/RHI/DeviceImageView.h>
  11. #include <Atom/RHI/ShaderResourceGroupPool.h>
  12. #include <Atom/RHI/RHISystemInterface.h>
  13. #include <AzCore/Console/IConsole.h>
  14. namespace AZ::RHI
  15. {
  16. ResultCode ShaderResourceGroupPool::Init(
  17. MultiDevice::DeviceMask deviceMask, const ShaderResourceGroupPoolDescriptor& descriptor)
  18. {
  19. if (Validation::IsEnabled())
  20. {
  21. if (descriptor.m_layout == nullptr)
  22. {
  23. AZ_Error("ShaderResourceGroupPool", false, "ShaderResourceGroupPoolDescriptor::m_layout must not be null.");
  24. return ResultCode::InvalidArgument;
  25. }
  26. }
  27. ResultCode resultCode = ResourcePool::Init(
  28. deviceMask,
  29. [this, &descriptor]()
  30. {
  31. IterateDevices(
  32. [this, &descriptor](int deviceIndex)
  33. {
  34. auto* device = RHISystemInterface::Get()->GetDevice(deviceIndex);
  35. m_deviceObjects[deviceIndex] = Factory::Get().CreateShaderResourceGroupPool();
  36. GetDeviceShaderResourceGroupPool(deviceIndex)->Init(*device, descriptor);
  37. return true;
  38. });
  39. return ResultCode::Success;
  40. });
  41. if (resultCode != ResultCode::Success)
  42. {
  43. // Reset already initialized device-specific ShaderResourceGroupPools and set deviceMask to 0
  44. m_deviceObjects.clear();
  45. MultiDeviceObject::Init(static_cast<MultiDevice::DeviceMask>(0u));
  46. return resultCode;
  47. }
  48. m_descriptor = descriptor;
  49. m_hasBufferGroup = m_descriptor.m_layout->GetGroupSizeForBuffers() > 0;
  50. m_hasImageGroup = m_descriptor.m_layout->GetGroupSizeForImages() > 0;
  51. m_hasSamplerGroup = m_descriptor.m_layout->GetGroupSizeForSamplers() > 0;
  52. m_hasConstants = m_descriptor.m_layout->GetConstantDataSize() > 0;
  53. return ResultCode::Success;
  54. }
  55. ResultCode ShaderResourceGroupPool::InitGroup(ShaderResourceGroup& group)
  56. {
  57. ResultCode resultCode = ResourcePool::InitResource(
  58. &group,
  59. [this, &group]()
  60. {
  61. return IterateObjects<DeviceShaderResourceGroupPool>([this, &group](auto deviceIndex, [[maybe_unused]] auto deviceShaderResourceGroupPool)
  62. {
  63. group.m_deviceObjects[deviceIndex] = Factory::Get().CreateShaderResourceGroup();
  64. return GetDeviceShaderResourceGroupPool(deviceIndex)->InitGroup(*group.GetDeviceShaderResourceGroup(deviceIndex));
  65. });
  66. });
  67. if (resultCode == ResultCode::Success)
  68. {
  69. const ShaderResourceGroupLayout* layout = GetLayout();
  70. // Pre-initialize the data so that we can build view diffs later.
  71. group.m_Data = ShaderResourceGroupData(GetDeviceMask(), layout);
  72. // Cache off the binding slot for one less indirection.
  73. group.m_bindingSlot = layout->GetBindingSlot();
  74. }
  75. else
  76. {
  77. // Reset already initialized device-specific ShaderResourceGroupPools and set deviceMask to 0
  78. m_deviceObjects.clear();
  79. MultiDeviceObject::Init(static_cast<MultiDevice::DeviceMask>(0u));
  80. }
  81. return resultCode;
  82. }
  83. void ShaderResourceGroupPool::CompileGroupsBegin()
  84. {
  85. IterateObjects<DeviceShaderResourceGroupPool>([]([[maybe_unused]] auto deviceIndex, auto deviceShaderResourceGroupPool)
  86. {
  87. deviceShaderResourceGroupPool->CompileGroupsBegin();
  88. });
  89. }
  90. void ShaderResourceGroupPool::CompileGroupsEnd()
  91. {
  92. IterateObjects<DeviceShaderResourceGroupPool>([]([[maybe_unused]] auto deviceIndex, auto deviceShaderResourceGroupPool)
  93. {
  94. deviceShaderResourceGroupPool->CompileGroupsEnd();
  95. });
  96. }
  97. uint32_t ShaderResourceGroupPool::GetGroupsToCompileCount() const
  98. {
  99. auto groupCount{ 0u };
  100. IterateObjects<DeviceShaderResourceGroupPool>([&groupCount]([[maybe_unused]] auto deviceIndex, auto deviceShaderResourceGroupPool)
  101. {
  102. groupCount += deviceShaderResourceGroupPool->GetGroupsToCompileCount();
  103. });
  104. return groupCount;
  105. }
  106. ResultCode ShaderResourceGroupPool::CompileGroup(
  107. ShaderResourceGroup& shaderResourceGroup, const ShaderResourceGroupData& shaderResourceGroupData)
  108. {
  109. return shaderResourceGroup.IterateObjects<DeviceShaderResourceGroup>([this, &shaderResourceGroupData](auto deviceIndex, auto deviceShaderResourceGroup)
  110. {
  111. return GetDeviceShaderResourceGroupPool(deviceIndex)->CompileGroup(
  112. *deviceShaderResourceGroup, shaderResourceGroupData.GetDeviceShaderResourceGroupData(deviceIndex));
  113. });
  114. }
  115. void ShaderResourceGroupPool::CompileGroupsForInterval(Interval interval)
  116. {
  117. auto doOverlap = [](Interval groupInterval, Interval givenInterval)
  118. {
  119. return (groupInterval.m_min < givenInterval.m_max) && (groupInterval.m_max > givenInterval.m_min);
  120. };
  121. auto currentStart{ 0u };
  122. IterateObjects<DeviceShaderResourceGroupPool>([&doOverlap, &interval, &currentStart]([[maybe_unused]] auto deviceIndex, auto deviceShaderResourceGroupPool)
  123. {
  124. auto groupsToCompile{ static_cast<int>(deviceShaderResourceGroupPool->GetGroupsToCompileCount()) };
  125. if (doOverlap({ currentStart, currentStart + groupsToCompile }, interval))
  126. {
  127. auto startOffset{ static_cast<int>(currentStart) - static_cast<int>(interval.m_min) };
  128. auto endOffset{ static_cast<int>(currentStart + groupsToCompile) - static_cast<int>(interval.m_max) };
  129. deviceShaderResourceGroupPool->CompileGroupsForInterval(
  130. { static_cast<uint32_t>((startOffset <= 0) ? 0 : startOffset),
  131. static_cast<uint32_t>((endOffset <= 0) ? groupsToCompile : groupsToCompile - endOffset) });
  132. }
  133. currentStart += groupsToCompile;
  134. });
  135. }
  136. const ShaderResourceGroupPoolDescriptor& ShaderResourceGroupPool::GetDescriptor() const
  137. {
  138. return m_descriptor;
  139. }
  140. const ShaderResourceGroupLayout* ShaderResourceGroupPool::GetLayout() const
  141. {
  142. AZ_Assert(m_descriptor.m_layout, "Shader resource group layout is null");
  143. return m_descriptor.m_layout.get();
  144. }
  145. bool ShaderResourceGroupPool::HasConstants() const
  146. {
  147. return m_hasConstants;
  148. }
  149. bool ShaderResourceGroupPool::HasBufferGroup() const
  150. {
  151. return m_hasBufferGroup;
  152. }
  153. bool ShaderResourceGroupPool::HasImageGroup() const
  154. {
  155. return m_hasImageGroup;
  156. }
  157. bool ShaderResourceGroupPool::HasSamplerGroup() const
  158. {
  159. return m_hasSamplerGroup;
  160. }
  161. void ShaderResourceGroupPool::Shutdown()
  162. {
  163. IterateObjects<DeviceShaderResourceGroupPool>([]([[maybe_unused]] auto deviceIndex, auto deviceShaderResourceGroupPool)
  164. {
  165. deviceShaderResourceGroupPool->Shutdown();
  166. });
  167. ResourcePool::Shutdown();
  168. }
  169. } // namespace AZ::RHI