BsSamplerOverrides.cpp 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. #include "BsSamplerOverrides.h"
  2. #include "BsRenderBeastOptions.h"
  3. #include "BsMaterial.h"
  4. #include "BsGpuParams.h"
  5. #include "BsGpuParamDesc.h"
  6. #include "BsSamplerState.h"
  7. #include "BsRenderStateManager.h"
  8. namespace BansheeEngine
  9. {
  10. MaterialSamplerOverrides* SamplerOverrideUtility::generateSamplerOverrides(const SPtr<MaterialCore>& material, const SPtr<RenderBeastOptions>& options)
  11. {
  12. UINT32 numPasses = material->getNumPasses();
  13. // First pass just determine if we even need to override and count the number of sampler states
  14. UINT32 totalNumSamplerStates = 0;
  15. for (UINT32 i = 0; i < numPasses; i++)
  16. {
  17. SPtr<PassParametersCore> passParams = material->getPassParameters(i);
  18. UINT32 maxSamplerSlot = 0;
  19. for (UINT32 j = 0; j < PassParametersCore::NUM_PARAMS; j++)
  20. {
  21. SPtr<GpuParamsCore> params = passParams->getParamByIdx(j);
  22. if (params == nullptr)
  23. continue;
  24. const GpuParamDesc& paramDesc = params->getParamDesc();
  25. for (auto iter = paramDesc.samplers.begin(); iter != paramDesc.samplers.end(); ++iter)
  26. {
  27. UINT32 slot = iter->second.slot;
  28. maxSamplerSlot = std::max(maxSamplerSlot, slot + 1);
  29. }
  30. totalNumSamplerStates += maxSamplerSlot;
  31. }
  32. }
  33. UINT32 outputSize = sizeof(MaterialSamplerOverrides) +
  34. numPasses * (sizeof(PassSamplerOverrides) + PassParametersCore::NUM_PARAMS * sizeof(StageSamplerOverrides)) +
  35. totalNumSamplerStates * sizeof(SPtr<SamplerStateCore>);
  36. UINT8* outputData = (UINT8*)bs_alloc(outputSize);
  37. MaterialSamplerOverrides* output = (MaterialSamplerOverrides*)outputData;
  38. outputData += sizeof(MaterialSamplerOverrides);
  39. output->refCount = 0;
  40. output->numPasses = numPasses;
  41. output->passes = (PassSamplerOverrides*)outputData;
  42. outputData += sizeof(PassSamplerOverrides) * numPasses;
  43. bs_frame_mark();
  44. {
  45. FrameUnorderedMap<SPtr<SamplerStateCore>, SPtr<SamplerStateCore>> overrideMap;
  46. for (UINT32 i = 0; i < numPasses; i++)
  47. {
  48. PassSamplerOverrides& passOverrides = output->passes[i];
  49. passOverrides.numStages = PassParametersCore::NUM_PARAMS;
  50. passOverrides.stages = (StageSamplerOverrides*)outputData;
  51. outputData += sizeof(StageSamplerOverrides) * PassParametersCore::NUM_PARAMS;
  52. SPtr<PassParametersCore> passParams = material->getPassParameters(i);
  53. for (UINT32 j = 0; j < passOverrides.numStages; j++)
  54. {
  55. StageSamplerOverrides& stageOverrides = passOverrides.stages[j];
  56. stageOverrides.numStates = 0;
  57. stageOverrides.stateOverrides = (SPtr<SamplerStateCore>*)outputData;
  58. SPtr<GpuParamsCore> params = passParams->getParamByIdx(j);
  59. if (params == nullptr)
  60. continue;
  61. const GpuParamDesc& paramDesc = params->getParamDesc();
  62. for (auto iter = paramDesc.samplers.begin(); iter != paramDesc.samplers.end(); ++iter)
  63. {
  64. UINT32 slot = iter->second.slot;
  65. while (slot >= stageOverrides.numStates)
  66. {
  67. new (&stageOverrides.stateOverrides[stageOverrides.numStates]) SPtr<SamplerStateCore>();
  68. stageOverrides.numStates++;
  69. }
  70. stageOverrides.numStates = std::max(stageOverrides.numStates, slot + 1);
  71. SPtr<SamplerStateCore> samplerState = params->getSamplerState(slot);
  72. if (samplerState == nullptr)
  73. samplerState = SamplerStateCore::getDefault();
  74. bool needsOverride = checkNeedsOverride(samplerState, options);
  75. if (needsOverride)
  76. {
  77. auto findIter = overrideMap.find(samplerState);
  78. if (findIter != overrideMap.end())
  79. {
  80. stageOverrides.stateOverrides[slot] = findIter->second;
  81. }
  82. else
  83. {
  84. SPtr<SamplerStateCore> newState = generateSamplerOverride(samplerState, options);
  85. overrideMap[samplerState] = newState;
  86. stageOverrides.stateOverrides[slot] = newState;
  87. }
  88. }
  89. else
  90. {
  91. stageOverrides.stateOverrides[slot] = samplerState;
  92. }
  93. }
  94. outputData += sizeof(SPtr<SamplerStateCore>) * stageOverrides.numStates;
  95. }
  96. }
  97. }
  98. bs_frame_clear();
  99. return output;
  100. }
  101. void SamplerOverrideUtility::destroySamplerOverrides(MaterialSamplerOverrides* overrides)
  102. {
  103. if (overrides != nullptr)
  104. {
  105. for (UINT32 i = 0; i < overrides->numPasses; i++)
  106. {
  107. PassSamplerOverrides& passOverrides = overrides->passes[i];
  108. for (UINT32 j = 0; j < passOverrides.numStages; j++)
  109. {
  110. StageSamplerOverrides& stageOverrides = passOverrides.stages[j];
  111. for (UINT32 k = 0; k < stageOverrides.numStates; k++)
  112. stageOverrides.stateOverrides[k].~SPtr<SamplerStateCore>();
  113. }
  114. }
  115. bs_free(overrides);
  116. }
  117. }
  118. bool SamplerOverrideUtility::checkNeedsOverride(const SPtr<SamplerStateCore>& samplerState, const SPtr<RenderBeastOptions>& options)
  119. {
  120. const SamplerProperties& props = samplerState->getProperties();
  121. switch (options->filtering)
  122. {
  123. case RenderBeastFiltering::Bilinear:
  124. {
  125. if (props.getTextureFiltering(FT_MIN) != FO_LINEAR)
  126. return true;
  127. if (props.getTextureFiltering(FT_MAG) != FO_LINEAR)
  128. return true;
  129. if (props.getTextureFiltering(FT_MIP) != FO_POINT)
  130. return true;
  131. }
  132. break;
  133. case RenderBeastFiltering::Trilinear:
  134. {
  135. if (props.getTextureFiltering(FT_MIN) != FO_LINEAR)
  136. return true;
  137. if (props.getTextureFiltering(FT_MAG) != FO_LINEAR)
  138. return true;
  139. if (props.getTextureFiltering(FT_MIP) != FO_LINEAR)
  140. return true;
  141. }
  142. break;
  143. case RenderBeastFiltering::Anisotropic:
  144. {
  145. if (props.getTextureFiltering(FT_MIN) != FO_ANISOTROPIC)
  146. return true;
  147. if (props.getTextureFiltering(FT_MAG) != FO_ANISOTROPIC)
  148. return true;
  149. if (props.getTextureFiltering(FT_MIP) != FO_ANISOTROPIC)
  150. return true;
  151. if (props.getTextureAnisotropy() != options->anisotropyMax)
  152. return true;
  153. }
  154. break;
  155. }
  156. return false;
  157. }
  158. SPtr<SamplerStateCore> SamplerOverrideUtility::generateSamplerOverride(const SPtr<SamplerStateCore>& samplerState, const SPtr<RenderBeastOptions>& options)
  159. {
  160. const SamplerProperties& props = samplerState->getProperties();
  161. SAMPLER_STATE_DESC desc = props.getDesc();
  162. switch (options->filtering)
  163. {
  164. case RenderBeastFiltering::Bilinear:
  165. desc.minFilter = FO_LINEAR;
  166. desc.magFilter = FO_LINEAR;
  167. desc.mipFilter = FO_POINT;
  168. break;
  169. case RenderBeastFiltering::Trilinear:
  170. desc.minFilter = FO_LINEAR;
  171. desc.magFilter = FO_LINEAR;
  172. desc.mipFilter = FO_LINEAR;
  173. break;
  174. case RenderBeastFiltering::Anisotropic:
  175. desc.minFilter = FO_ANISOTROPIC;
  176. desc.magFilter = FO_ANISOTROPIC;
  177. desc.mipFilter = FO_ANISOTROPIC;
  178. break;
  179. }
  180. desc.maxAniso = options->anisotropyMax;
  181. return RenderStateCoreManager::instance().createSamplerState(desc);
  182. }
  183. }