mirror of
https://github.com/barkeser2002/flower.git
synced 2026-09-25 14:56:14 +03:00
1041 lines
32 KiB
C++
1041 lines
32 KiB
C++
#include "Pch.h"
|
|
#include "SceneTextures.h"
|
|
#include "RenderSettingContext.h"
|
|
#include "../AssetSystem/TextureManager.h"
|
|
|
|
namespace Flower
|
|
{
|
|
SceneTextures::SceneTextures(RendererInterface* in)
|
|
: m_renderer(in)
|
|
, m_rtPool(in->getRTPool())
|
|
{
|
|
|
|
}
|
|
|
|
void SceneTextures::release()
|
|
{
|
|
m_hdrSceneColor = nullptr;
|
|
m_hdrSceneColorUpscale = nullptr;
|
|
|
|
m_depthTexture = nullptr;
|
|
|
|
m_gbufferA = nullptr;
|
|
m_gbufferB = nullptr;
|
|
m_gbufferS = nullptr;
|
|
|
|
m_sdsmDepthTextures = nullptr;
|
|
m_sdsmShadowMask = nullptr;
|
|
|
|
m_gbufferUpscaleReactive = nullptr;
|
|
m_gbufferUpscaleTranslucencyAndComposition = nullptr;
|
|
|
|
m_atmosphereMultiScatter = nullptr;
|
|
m_atmosphereSkyView = nullptr;
|
|
m_atmosphereTransmittance = nullptr;
|
|
m_atmosphereFroxelScatter = nullptr;
|
|
m_atmosphereEnvCapture = nullptr;
|
|
}
|
|
|
|
PoolImageSharedRef SceneTextures::getHdrSceneColor()
|
|
{
|
|
if (!m_hdrSceneColor)
|
|
{
|
|
m_hdrSceneColor = m_rtPool->createPoolImage(
|
|
"HdrSceneColor",
|
|
m_renderer->getRenderWidth(),
|
|
m_renderer->getRenderHeight(),
|
|
RTFormats::hdrSceneColor(),
|
|
RTUsages::hdrSceneColor()
|
|
);
|
|
}
|
|
|
|
return m_hdrSceneColor;
|
|
}
|
|
|
|
PoolImageSharedRef SceneTextures::getHdrSceneColorUpscale()
|
|
{
|
|
if (!m_hdrSceneColorUpscale)
|
|
{
|
|
m_hdrSceneColorUpscale = m_rtPool->createPoolImage(
|
|
"HdrSceneColorUpscale",
|
|
m_renderer->getDisplayWidth(),
|
|
m_renderer->getDisplayHeight(),
|
|
RTFormats::hdrSceneColor(),
|
|
RTUsages::hdrSceneColor()
|
|
);
|
|
}
|
|
|
|
return m_hdrSceneColorUpscale;
|
|
}
|
|
|
|
PoolImageSharedRef SceneTextures::setHdrSceneColorUpscale(PoolImageSharedRef newI)
|
|
{
|
|
PoolImageSharedRef src = m_hdrSceneColorUpscale;
|
|
m_hdrSceneColorUpscale = newI;
|
|
|
|
return src;
|
|
}
|
|
|
|
PoolImageSharedRef SceneTextures::getGbufferA()
|
|
{
|
|
if (!m_gbufferA)
|
|
{
|
|
m_gbufferA = m_rtPool->createPoolImage(
|
|
"GBufferA",
|
|
m_renderer->getRenderWidth(),
|
|
m_renderer->getRenderHeight(),
|
|
RTFormats::gbufferA(),
|
|
RTUsages::gbuffer()
|
|
);
|
|
}
|
|
|
|
return m_gbufferA;
|
|
}
|
|
|
|
PoolImageSharedRef SceneTextures::getGbufferB()
|
|
{
|
|
if (!m_gbufferB)
|
|
{
|
|
m_gbufferB = m_rtPool->createPoolImage(
|
|
"GBufferB",
|
|
m_renderer->getRenderWidth(),
|
|
m_renderer->getRenderHeight(),
|
|
RTFormats::gbufferB(),
|
|
RTUsages::gbuffer()
|
|
);
|
|
}
|
|
|
|
return m_gbufferB;
|
|
}
|
|
|
|
PoolImageSharedRef SceneTextures::getGbufferS()
|
|
{
|
|
if (!m_gbufferS)
|
|
{
|
|
m_gbufferS = m_rtPool->createPoolImage(
|
|
"GBufferS",
|
|
m_renderer->getRenderWidth(),
|
|
m_renderer->getRenderHeight(),
|
|
RTFormats::gbufferS(),
|
|
RTUsages::gbuffer()
|
|
);
|
|
}
|
|
|
|
return m_gbufferS;
|
|
}
|
|
|
|
PoolImageSharedRef SceneTextures::getGbufferV()
|
|
{
|
|
if (!m_gbufferV)
|
|
{
|
|
m_gbufferV = m_rtPool->createPoolImage(
|
|
"GBufferV",
|
|
m_renderer->getRenderWidth(),
|
|
m_renderer->getRenderHeight(),
|
|
RTFormats::gbufferV(),
|
|
RTUsages::gbuffer()
|
|
);
|
|
}
|
|
|
|
return m_gbufferV;
|
|
}
|
|
|
|
PoolImageSharedRef SceneTextures::getGbufferUpscaleReactive()
|
|
{
|
|
if (!m_gbufferUpscaleReactive)
|
|
{
|
|
m_gbufferUpscaleReactive = m_rtPool->createPoolImage(
|
|
"GBufferUpscaleReactive",
|
|
m_renderer->getRenderWidth(),
|
|
m_renderer->getRenderHeight(),
|
|
RTFormats::gbufferUpscaleReactive(),
|
|
RTUsages::gbuffer()
|
|
);
|
|
}
|
|
|
|
return m_gbufferUpscaleReactive;
|
|
}
|
|
|
|
PoolImageSharedRef SceneTextures::getGbufferUpscaleTranslucencyAndComposition()
|
|
{
|
|
if (!m_gbufferUpscaleTranslucencyAndComposition)
|
|
{
|
|
m_gbufferUpscaleTranslucencyAndComposition = m_rtPool->createPoolImage(
|
|
"GBufferUpscaleTranslucencyAndComposition",
|
|
m_renderer->getRenderWidth(),
|
|
m_renderer->getRenderHeight(),
|
|
RTFormats::gbufferUpscaleTranslucencyAndComposition(),
|
|
RTUsages::gbuffer()
|
|
);
|
|
}
|
|
|
|
return m_gbufferUpscaleTranslucencyAndComposition;
|
|
}
|
|
|
|
PoolImageSharedRef SceneTextures::getDepth()
|
|
{
|
|
if (!m_depthTexture)
|
|
{
|
|
m_depthTexture = m_rtPool->createPoolImage(
|
|
"DepthZ",
|
|
m_renderer->getRenderWidth(),
|
|
m_renderer->getRenderHeight(),
|
|
RTFormats::depth(),
|
|
RTUsages::depth()
|
|
);
|
|
}
|
|
|
|
return m_depthTexture;
|
|
}
|
|
|
|
void SceneTextures::allocateSDSMTexture(uint32_t dimXY, uint32_t cascadeCount)
|
|
{
|
|
CHECK(m_sdsmDepthTextures == nullptr);
|
|
|
|
m_sdsmDepthTextures = m_rtPool->createPoolImage(
|
|
"SDSMDepth",
|
|
dimXY * cascadeCount,
|
|
dimXY,
|
|
RTFormats::depth(),
|
|
RTUsages::depth()
|
|
);
|
|
|
|
|
|
}
|
|
|
|
PoolImageSharedRef SceneTextures::getSDSMDepth()
|
|
{
|
|
CHECK(m_sdsmDepthTextures);
|
|
|
|
return m_sdsmDepthTextures;
|
|
}
|
|
|
|
bool SceneTextures::isSDSMDepthExist() const
|
|
{
|
|
return m_sdsmDepthTextures != nullptr;
|
|
}
|
|
|
|
PoolImageSharedRef SceneTextures::getSDSMShadowMask()
|
|
{
|
|
if (!m_sdsmShadowMask)
|
|
{
|
|
m_sdsmShadowMask = m_rtPool->createPoolImage(
|
|
"SDSMShadowMask",
|
|
m_renderer->getRenderWidth(),
|
|
m_renderer->getRenderHeight(),
|
|
RTFormats::sdsmShadowMask(),
|
|
RTUsages::sdsmMask()
|
|
);
|
|
}
|
|
|
|
return m_sdsmShadowMask;
|
|
}
|
|
|
|
PoolImageSharedRef SceneTextures::getAtmosphereTransmittance()
|
|
{
|
|
if (!m_atmosphereTransmittance)
|
|
{
|
|
m_atmosphereTransmittance = m_rtPool->createPoolImage(
|
|
"AtmosphereTransmittance",
|
|
256, // Must can divide by 8.
|
|
64, // Must can divide by 8.
|
|
VK_FORMAT_R16G16B16A16_SFLOAT,
|
|
VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT
|
|
);
|
|
}
|
|
|
|
return m_atmosphereTransmittance;
|
|
}
|
|
|
|
constexpr auto SkyViewLookupDim = 256;
|
|
|
|
PoolImageSharedRef SceneTextures::getAtmosphereSkyView()
|
|
{
|
|
if (!m_atmosphereSkyView)
|
|
{
|
|
m_atmosphereSkyView = m_rtPool->createPoolImage(
|
|
"AtmosphereSkyView",
|
|
SkyViewLookupDim,
|
|
SkyViewLookupDim,
|
|
VK_FORMAT_R16G16B16A16_SFLOAT,
|
|
VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT
|
|
);
|
|
}
|
|
|
|
return m_atmosphereSkyView;
|
|
}
|
|
|
|
PoolImageSharedRef SceneTextures::getAtmosphereSkyViewCloudBottom()
|
|
{
|
|
if (!m_atmosphereSkyViewCloudBottom)
|
|
{
|
|
m_atmosphereSkyViewCloudBottom = m_rtPool->createPoolImage(
|
|
"AtmosphereSkyViewCloudBottom",
|
|
SkyViewLookupDim,
|
|
SkyViewLookupDim,
|
|
VK_FORMAT_R16G16B16A16_SFLOAT,
|
|
VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT
|
|
);
|
|
}
|
|
|
|
return m_atmosphereSkyViewCloudBottom;
|
|
}
|
|
PoolImageSharedRef SceneTextures::getAtmosphereSkyViewCloudTop()
|
|
{
|
|
if (!m_atmosphereSkyViewCloudTop)
|
|
{
|
|
m_atmosphereSkyViewCloudTop = m_rtPool->createPoolImage(
|
|
"AtmosphereSkyViewCloudTop",
|
|
SkyViewLookupDim,
|
|
SkyViewLookupDim,
|
|
VK_FORMAT_R16G16B16A16_SFLOAT,
|
|
VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT
|
|
);
|
|
}
|
|
|
|
return m_atmosphereSkyViewCloudTop;
|
|
}
|
|
PoolImageSharedRef SceneTextures::getAtmosphereMultiScatter()
|
|
{
|
|
if (!m_atmosphereMultiScatter)
|
|
{
|
|
m_atmosphereMultiScatter = m_rtPool->createPoolImage(
|
|
"AtmosphereMultiScatter",
|
|
32, // Must can divide by 8.
|
|
32, // Must can divide by 8.
|
|
VK_FORMAT_R16G16B16A16_SFLOAT,
|
|
VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT
|
|
);
|
|
}
|
|
|
|
return m_atmosphereMultiScatter;
|
|
}
|
|
|
|
PoolImageSharedRef SceneTextures::getAtmosphereFroxelScatter()
|
|
{
|
|
if (!m_atmosphereFroxelScatter)
|
|
{
|
|
m_atmosphereFroxelScatter = m_rtPool->createPoolImage(
|
|
"AtmosphereFroxelScatter",
|
|
32, // Must can divide by 8.
|
|
32, // Must can divide by 8.
|
|
VK_FORMAT_R16G16B16A16_SFLOAT,
|
|
VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
|
|
1, // Mipmap count.
|
|
32 // Depth
|
|
);
|
|
}
|
|
|
|
return m_atmosphereFroxelScatter;
|
|
}
|
|
|
|
PoolImageSharedRef SceneTextures::getAtmosphereEnvCapture()
|
|
{
|
|
if (!m_atmosphereEnvCapture)
|
|
{
|
|
// Need mipmaps.
|
|
m_atmosphereEnvCapture = m_rtPool->createPoolCubeImage(
|
|
"AtmosphereEnvCapture",
|
|
128, // Must can divide by 8.
|
|
128, // Must can divide by 8.
|
|
VK_FORMAT_R16G16B16A16_SFLOAT,
|
|
VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT,
|
|
-1
|
|
);
|
|
}
|
|
|
|
return m_atmosphereEnvCapture;
|
|
}
|
|
|
|
PoolImageSharedRef SceneTextures::getSkyPrefilter()
|
|
{
|
|
if (!m_atmosphereEnvPrefilter)
|
|
{
|
|
// Need mipmaps.
|
|
m_atmosphereEnvPrefilter = m_rtPool->createPoolCubeImage(
|
|
"SkyIBLPrefilter",
|
|
128, // Must can divide by 8.
|
|
128, // Must can divide by 8.
|
|
VK_FORMAT_R16G16B16A16_SFLOAT,
|
|
VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
|
|
-1
|
|
);
|
|
}
|
|
|
|
return m_atmosphereEnvPrefilter;
|
|
}
|
|
|
|
PoolImageSharedRef SceneTextures::getSkyIrradiance()
|
|
{
|
|
if (!m_atmosphereEnvIrradiance)
|
|
{
|
|
m_atmosphereEnvIrradiance = m_rtPool->createPoolCubeImage(
|
|
"SkyIBLIrradiance",
|
|
32, // Must can divide by 8.
|
|
32, // Must can divide by 8.
|
|
VK_FORMAT_R16G16B16A16_SFLOAT,
|
|
VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT
|
|
);
|
|
}
|
|
|
|
return m_atmosphereEnvIrradiance;
|
|
}
|
|
|
|
PoolImageSharedRef StaticTextures::getBRDFLut()
|
|
{
|
|
CHECK(m_brdfLut && "You should call initBRDFLut() once when engine init.");
|
|
return m_brdfLut;
|
|
}
|
|
|
|
bool StaticTextures::isSkyIBLReady() const
|
|
{
|
|
return m_brdfLut && m_iblSkyIrradiance && m_iblSkyPrefilter;
|
|
}
|
|
|
|
PoolImageSharedRef StaticTextures::getCloudBasicNoise()
|
|
{
|
|
CHECK(m_cloudBasicNoise && "You should call initCloudNoise() once when engine init.");
|
|
return m_cloudBasicNoise;
|
|
}
|
|
|
|
PoolImageSharedRef StaticTextures::getCloudWorleyNoise()
|
|
{
|
|
CHECK(m_cloudWorleyNoise && "You should call initCloudNoise() once when engine init.");
|
|
return m_cloudWorleyNoise;
|
|
}
|
|
|
|
void StaticTextures::init()
|
|
{
|
|
m_passCollector = std::make_unique<PassCollector>();
|
|
m_rtPool = std::make_unique<RenderTexturePool>();
|
|
|
|
auto cmd = RHI::get()->createMajorGraphicsCommandBuffer();
|
|
RHICheck(vkResetCommandBuffer(cmd, 0));
|
|
VkCommandBufferBeginInfo cmdBeginInfo = RHICommandbufferBeginInfo(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
|
|
RHICheck(vkBeginCommandBuffer(cmd, &cmdBeginInfo));
|
|
{
|
|
// Init basic resource for engine.
|
|
initIBL(cmd);
|
|
|
|
initCloudTexture(cmd);
|
|
}
|
|
RHICheck(vkEndCommandBuffer(cmd));
|
|
|
|
VkPipelineStageFlags waitFlags = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT;
|
|
RHISubmitInfo cmdSubmitInfo{};
|
|
cmdSubmitInfo.setWaitStage(&waitFlags).setCommandBuffer(&cmd, 1);
|
|
std::vector<VkSubmitInfo> infosRawSubmit{ cmdSubmitInfo };
|
|
RHI::get()->submitNoFence((uint32_t)infosRawSubmit.size(), infosRawSubmit.data());
|
|
|
|
vkDeviceWaitIdle(RHI::Device);
|
|
|
|
globalBlueNoise.init();
|
|
}
|
|
|
|
void StaticTextures::tick()
|
|
{
|
|
m_rtPool->tick();
|
|
}
|
|
|
|
void StaticTextures::release()
|
|
{
|
|
vkDeviceWaitIdle(RHI::Device);
|
|
m_rtPool.reset();
|
|
m_passCollector.reset();
|
|
globalBlueNoise.release();
|
|
}
|
|
|
|
struct IBLPrefilterPushConst
|
|
{
|
|
float perceptualRoughness;
|
|
int samplesCount; // 1024
|
|
float maxBrightValue; // 10.0f
|
|
float filterRoughnessMin; // 0.05f
|
|
int updateFaceIndex;
|
|
};
|
|
|
|
struct IBLIrradiancePushConst
|
|
{
|
|
uint32_t convolutionSampleCount; // 4096
|
|
int updateFaceIndex;
|
|
};
|
|
|
|
class IBLComputePass : public PassInterface
|
|
{
|
|
public:
|
|
VkPipeline lutPipeline = VK_NULL_HANDLE;
|
|
VkPipelineLayout lutPipelineLayout = VK_NULL_HANDLE;
|
|
VkDescriptorSetLayout lutSetLayout = VK_NULL_HANDLE;
|
|
|
|
VkPipeline irradiancePipeline = VK_NULL_HANDLE;
|
|
VkPipelineLayout irradiancePipelineLayout = VK_NULL_HANDLE;
|
|
VkDescriptorSetLayout irradianceSetLayout = VK_NULL_HANDLE;
|
|
|
|
VkPipeline sphericalMapToCubePipeline = VK_NULL_HANDLE;
|
|
VkPipelineLayout sphericalMapToCubePipelineLayout = VK_NULL_HANDLE;
|
|
VkDescriptorSetLayout sphericalMapToCubeSetLayout = VK_NULL_HANDLE;
|
|
|
|
VkPipeline prefilterPipeline = VK_NULL_HANDLE;
|
|
VkPipelineLayout prefilterPipelineLayout = VK_NULL_HANDLE;
|
|
VkDescriptorSetLayout prefilterSetLayout = VK_NULL_HANDLE;
|
|
|
|
public:
|
|
virtual void init() override
|
|
{
|
|
CHECK(lutPipeline == VK_NULL_HANDLE);
|
|
CHECK(lutPipelineLayout == VK_NULL_HANDLE);
|
|
CHECK(lutSetLayout == VK_NULL_HANDLE);
|
|
|
|
// Config code.
|
|
RHI::get()->descriptorFactoryBegin()
|
|
.bindNoInfo(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT, 0) // outLut
|
|
.buildNoInfoPush(lutSetLayout);
|
|
|
|
std::vector<VkDescriptorSetLayout> setLayouts =
|
|
{
|
|
lutSetLayout, // Owner setlayout.
|
|
};
|
|
auto shaderModule = RHI::ShaderManager->getShader("BRDFLut.comp.spv", true);
|
|
|
|
// Vulkan buid functions.
|
|
VkPipelineLayoutCreateInfo plci = RHIPipelineLayoutCreateInfo();
|
|
plci.setLayoutCount = (uint32_t)setLayouts.size();
|
|
plci.pSetLayouts = setLayouts.data();
|
|
lutPipelineLayout = RHI::get()->createPipelineLayout(plci);
|
|
VkPipelineShaderStageCreateInfo shaderStageCI{};
|
|
shaderStageCI.module = shaderModule;
|
|
shaderStageCI.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
|
|
shaderStageCI.stage = VK_SHADER_STAGE_COMPUTE_BIT;
|
|
shaderStageCI.pName = "main";
|
|
VkComputePipelineCreateInfo computePipelineCreateInfo{};
|
|
computePipelineCreateInfo.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;
|
|
computePipelineCreateInfo.layout = lutPipelineLayout;
|
|
computePipelineCreateInfo.flags = 0;
|
|
computePipelineCreateInfo.stage = shaderStageCI;
|
|
RHICheck(vkCreateComputePipelines(RHI::Device, nullptr, 1, &computePipelineCreateInfo, nullptr, &lutPipeline));
|
|
|
|
{
|
|
CHECK(sphericalMapToCubePipeline == VK_NULL_HANDLE);
|
|
CHECK(sphericalMapToCubePipelineLayout == VK_NULL_HANDLE);
|
|
CHECK(sphericalMapToCubeSetLayout == VK_NULL_HANDLE);
|
|
|
|
// Config code.
|
|
RHI::get()->descriptorFactoryBegin()
|
|
.bindNoInfo(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT, 0) // out cube
|
|
.bindNoInfo(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT, 1) // hdr src
|
|
.buildNoInfoPush(sphericalMapToCubeSetLayout);
|
|
|
|
std::vector<VkDescriptorSetLayout> setLayouts =
|
|
{
|
|
sphericalMapToCubeSetLayout, // Owner setlayout.
|
|
RHI::SamplerManager->getCommonDescriptorSetLayout()
|
|
};
|
|
auto shaderModule = RHI::ShaderManager->getShader("SphericalToCube.comp.spv", true);
|
|
|
|
// Vulkan buid functions.
|
|
VkPipelineLayoutCreateInfo plci = RHIPipelineLayoutCreateInfo();
|
|
plci.setLayoutCount = (uint32_t)setLayouts.size();
|
|
plci.pSetLayouts = setLayouts.data();
|
|
sphericalMapToCubePipelineLayout = RHI::get()->createPipelineLayout(plci);
|
|
VkPipelineShaderStageCreateInfo shaderStageCI{};
|
|
shaderStageCI.module = shaderModule;
|
|
shaderStageCI.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
|
|
shaderStageCI.stage = VK_SHADER_STAGE_COMPUTE_BIT;
|
|
shaderStageCI.pName = "main";
|
|
VkComputePipelineCreateInfo computePipelineCreateInfo{};
|
|
computePipelineCreateInfo.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;
|
|
computePipelineCreateInfo.layout = sphericalMapToCubePipelineLayout;
|
|
computePipelineCreateInfo.flags = 0;
|
|
computePipelineCreateInfo.stage = shaderStageCI;
|
|
RHICheck(vkCreateComputePipelines(RHI::Device, nullptr, 1, &computePipelineCreateInfo, nullptr, &sphericalMapToCubePipeline));
|
|
}
|
|
|
|
{
|
|
CHECK(irradiancePipeline == VK_NULL_HANDLE);
|
|
CHECK(irradiancePipelineLayout == VK_NULL_HANDLE);
|
|
CHECK(irradianceSetLayout == VK_NULL_HANDLE);
|
|
|
|
// Config code.
|
|
RHI::get()->descriptorFactoryBegin()
|
|
.bindNoInfo(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT, 0) // out irradiance
|
|
.bindNoInfo(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT, 1) // sample cube
|
|
.buildNoInfoPush(irradianceSetLayout);
|
|
|
|
std::vector<VkDescriptorSetLayout> setLayouts =
|
|
{
|
|
irradianceSetLayout, // Owner setlayout.
|
|
RHI::SamplerManager->getCommonDescriptorSetLayout()
|
|
};
|
|
auto shaderModule = RHI::ShaderManager->getShader("IBLIrradiance.comp.spv", true);
|
|
|
|
// Vulkan buid functions.
|
|
VkPipelineLayoutCreateInfo plci = RHIPipelineLayoutCreateInfo();
|
|
|
|
VkPushConstantRange pushConstRange{ .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT, .offset = 0, .size = sizeof(IBLIrradiancePushConst) };
|
|
plci.pushConstantRangeCount = 1;
|
|
plci.pPushConstantRanges = &pushConstRange;
|
|
|
|
plci.setLayoutCount = (uint32_t)setLayouts.size();
|
|
plci.pSetLayouts = setLayouts.data();
|
|
irradiancePipelineLayout = RHI::get()->createPipelineLayout(plci);
|
|
VkPipelineShaderStageCreateInfo shaderStageCI{};
|
|
shaderStageCI.module = shaderModule;
|
|
shaderStageCI.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
|
|
shaderStageCI.stage = VK_SHADER_STAGE_COMPUTE_BIT;
|
|
shaderStageCI.pName = "main";
|
|
VkComputePipelineCreateInfo computePipelineCreateInfo{};
|
|
computePipelineCreateInfo.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;
|
|
computePipelineCreateInfo.layout = irradiancePipelineLayout;
|
|
computePipelineCreateInfo.flags = 0;
|
|
computePipelineCreateInfo.stage = shaderStageCI;
|
|
RHICheck(vkCreateComputePipelines(RHI::Device, nullptr, 1, &computePipelineCreateInfo, nullptr, &irradiancePipeline));
|
|
}
|
|
|
|
{
|
|
CHECK(prefilterPipeline == VK_NULL_HANDLE);
|
|
CHECK(prefilterPipelineLayout == VK_NULL_HANDLE);
|
|
CHECK(prefilterSetLayout == VK_NULL_HANDLE);
|
|
|
|
// Config code.
|
|
RHI::get()->descriptorFactoryBegin()
|
|
.bindNoInfo(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT, 0) // out prefilter
|
|
.bindNoInfo(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT, 1) // sample cube
|
|
.buildNoInfoPush(prefilterSetLayout);
|
|
|
|
std::vector<VkDescriptorSetLayout> setLayouts =
|
|
{
|
|
prefilterSetLayout, // Owner setlayout.
|
|
RHI::SamplerManager->getCommonDescriptorSetLayout()
|
|
};
|
|
auto shaderModule = RHI::ShaderManager->getShader("IBLPrefilter.comp.spv", true);
|
|
|
|
// Vulkan buid functions.
|
|
VkPipelineLayoutCreateInfo plci = RHIPipelineLayoutCreateInfo();
|
|
|
|
VkPushConstantRange pushConstRange{ .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT, .offset = 0, .size = sizeof(IBLPrefilterPushConst) };
|
|
|
|
plci.pushConstantRangeCount = 1;
|
|
plci.pPushConstantRanges = &pushConstRange;
|
|
|
|
plci.setLayoutCount = (uint32_t)setLayouts.size();
|
|
plci.pSetLayouts = setLayouts.data();
|
|
prefilterPipelineLayout = RHI::get()->createPipelineLayout(plci);
|
|
VkPipelineShaderStageCreateInfo shaderStageCI{};
|
|
shaderStageCI.module = shaderModule;
|
|
shaderStageCI.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
|
|
shaderStageCI.stage = VK_SHADER_STAGE_COMPUTE_BIT;
|
|
shaderStageCI.pName = "main";
|
|
VkComputePipelineCreateInfo computePipelineCreateInfo{};
|
|
computePipelineCreateInfo.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;
|
|
computePipelineCreateInfo.layout = prefilterPipelineLayout;
|
|
computePipelineCreateInfo.flags = 0;
|
|
computePipelineCreateInfo.stage = shaderStageCI;
|
|
RHICheck(vkCreateComputePipelines(RHI::Device, nullptr, 1, &computePipelineCreateInfo, nullptr, &prefilterPipeline));
|
|
}
|
|
}
|
|
|
|
virtual void release() override
|
|
{
|
|
RHISafeRelease(lutPipeline);
|
|
RHISafeRelease(lutPipelineLayout);
|
|
lutSetLayout = VK_NULL_HANDLE;
|
|
|
|
RHISafeRelease(irradiancePipeline);
|
|
RHISafeRelease(irradiancePipelineLayout);
|
|
irradianceSetLayout = VK_NULL_HANDLE;
|
|
|
|
RHISafeRelease(sphericalMapToCubePipeline);
|
|
RHISafeRelease(sphericalMapToCubePipelineLayout);
|
|
sphericalMapToCubeSetLayout = VK_NULL_HANDLE;
|
|
|
|
RHISafeRelease(prefilterPipeline);
|
|
RHISafeRelease(prefilterPipelineLayout);
|
|
prefilterSetLayout = VK_NULL_HANDLE;
|
|
}
|
|
};
|
|
|
|
void StaticTextures::initIBL(VkCommandBuffer cmd)
|
|
{
|
|
auto* pass = m_passCollector->getPass<IBLComputePass>();
|
|
{
|
|
CHECK(m_brdfLut == nullptr && "BRDF lut only init once.");
|
|
m_brdfLut = m_rtPool->createPoolImage(
|
|
"BRDFLut",
|
|
256u,
|
|
256u,
|
|
RTFormats::brdfLut(),
|
|
RTUsages::brdfLut()
|
|
);
|
|
|
|
m_brdfLut->getImage().transitionLayout(cmd, VK_IMAGE_LAYOUT_GENERAL, buildBasicImageSubresource());
|
|
{
|
|
vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_COMPUTE, pass->lutPipeline);
|
|
|
|
VkDescriptorImageInfo lutImageInfo = RHIDescriptorImageInfoStorage(m_brdfLut->getImage().getView(buildBasicImageSubresource()));
|
|
std::vector<VkWriteDescriptorSet> writes
|
|
{
|
|
RHIPushWriteDescriptorSetImage(0, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &lutImageInfo),
|
|
};
|
|
|
|
// Push owner set #0.
|
|
RHI::PushDescriptorSetKHR(cmd, VK_PIPELINE_BIND_POINT_COMPUTE, pass->lutPipelineLayout, 0, uint32_t(writes.size()), writes.data());
|
|
|
|
vkCmdDispatch(cmd, getGroupCount(m_brdfLut->getImage().getExtent().width, 8), getGroupCount(m_brdfLut->getImage().getExtent().height, 8), 1);
|
|
}
|
|
m_brdfLut->getImage().transitionLayout(cmd, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, buildBasicImageSubresource());
|
|
}
|
|
}
|
|
|
|
void SceneTextures::bakeSkyIBL(VkCommandBuffer cmd, uint32_t faceIndex)
|
|
{
|
|
CHECK(faceIndex < 6u);
|
|
|
|
auto* pass = StaticTexturesManager::get()->getPasses()->getPass<IBLComputePass>();
|
|
|
|
auto skyEnvCube = getAtmosphereEnvCapture();
|
|
|
|
std::vector<VkDescriptorSet> compPassSets =
|
|
{
|
|
RHI::SamplerManager->getCommonDescriptorSet()
|
|
};
|
|
|
|
auto inCubeViewRangeAll = VkImageSubresourceRange
|
|
{
|
|
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
|
.baseMipLevel = 0,
|
|
.levelCount = skyEnvCube->getImage().getInfo().mipLevels,
|
|
.baseArrayLayer = 0,
|
|
.layerCount = 6
|
|
};
|
|
|
|
skyEnvCube->getImage().transitionLayout(cmd, VK_IMAGE_LAYOUT_GENERAL, inCubeViewRangeAll);
|
|
skyEnvCube->getImage().transitionLayout(cmd, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, inCubeViewRangeAll);
|
|
|
|
// Generate cubemap mips for filter.
|
|
{
|
|
auto cubemapViewRange = VkImageSubresourceRange
|
|
{
|
|
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
|
.baseMipLevel = 0,
|
|
.levelCount = 1,
|
|
.baseArrayLayer = faceIndex,
|
|
.layerCount = 1
|
|
};
|
|
|
|
// Mip 0 as src input.
|
|
skyEnvCube->getImage().transitionLayout(cmd, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, cubemapViewRange);
|
|
|
|
VkImageMemoryBarrier barrier{};
|
|
barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
|
|
barrier.image = skyEnvCube->getImage().getImage();
|
|
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
|
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
|
barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
|
barrier.subresourceRange.baseArrayLayer = faceIndex;
|
|
barrier.subresourceRange.layerCount = 1;
|
|
barrier.subresourceRange.levelCount = 1;
|
|
|
|
// Generate cubemap mips.
|
|
int32_t mipWidth = skyEnvCube->getImage().getExtent().width;
|
|
int32_t mipHeight = skyEnvCube->getImage().getExtent().height;
|
|
for (uint32_t i = 1; i < skyEnvCube->getImage().getInfo().mipLevels; i++)
|
|
{
|
|
// Layout for write.
|
|
barrier.subresourceRange.baseMipLevel = i;
|
|
barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
|
barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
|
|
barrier.srcAccessMask = VK_ACCESS_NONE;
|
|
barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
|
vkCmdPipelineBarrier(cmd,
|
|
VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0,
|
|
0, nullptr,
|
|
0, nullptr,
|
|
1, &barrier);
|
|
|
|
VkImageBlit blit{};
|
|
|
|
blit.srcOffsets[0] = { 0, 0, 0 };
|
|
blit.dstOffsets[0] = { 0, 0, 0 };
|
|
|
|
blit.srcOffsets[1] = { mipWidth, mipHeight, 1 };
|
|
blit.dstOffsets[1] = { mipWidth > 1 ? mipWidth / 2 : 1, mipHeight > 1 ? mipHeight / 2 : 1, 1 };
|
|
|
|
blit.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
|
blit.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
|
|
|
blit.srcSubresource.mipLevel = i - 1;
|
|
blit.dstSubresource.mipLevel = i;
|
|
|
|
blit.srcSubresource.baseArrayLayer = faceIndex;
|
|
blit.dstSubresource.baseArrayLayer = faceIndex;
|
|
|
|
blit.srcSubresource.layerCount = 1; // Cube map, only update one face
|
|
blit.dstSubresource.layerCount = 1;
|
|
|
|
vkCmdBlitImage(cmd,
|
|
skyEnvCube->getImage().getImage(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
|
skyEnvCube->getImage().getImage(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
|
1, &blit,
|
|
VK_FILTER_LINEAR
|
|
);
|
|
|
|
// Layout for read.
|
|
barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
|
|
barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
|
|
barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
|
barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
|
|
vkCmdPipelineBarrier(cmd,
|
|
VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0,
|
|
0, nullptr,
|
|
0, nullptr,
|
|
1, &barrier);
|
|
|
|
if (mipWidth > 1) mipWidth /= 2;
|
|
if (mipHeight > 1) mipHeight /= 2;
|
|
}
|
|
|
|
cubemapViewRange.levelCount = skyEnvCube->getImage().getInfo().mipLevels;
|
|
skyEnvCube->getImage().transitionLayout(cmd, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, cubemapViewRange);
|
|
}
|
|
|
|
skyEnvCube->getImage().transitionLayout(cmd, VK_IMAGE_LAYOUT_GENERAL, inCubeViewRangeAll);
|
|
skyEnvCube->getImage().transitionLayout(cmd, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, inCubeViewRangeAll);
|
|
VkDescriptorImageInfo hdrCubeInfo = RHIDescriptorImageInfoSample(skyEnvCube->getImage().getView(inCubeViewRangeAll, VK_IMAGE_VIEW_TYPE_CUBE));
|
|
|
|
// Irradiance Compute.
|
|
{
|
|
auto irradianceMap = getSkyIrradiance();
|
|
|
|
auto irradianceViewRange = VkImageSubresourceRange
|
|
{
|
|
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
|
.baseMipLevel = 0,
|
|
.levelCount = 1,
|
|
.baseArrayLayer = 0,
|
|
.layerCount = 6
|
|
};
|
|
|
|
irradianceMap->getImage().transitionLayout(cmd, VK_IMAGE_LAYOUT_GENERAL, irradianceViewRange);
|
|
{
|
|
vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_COMPUTE, pass->irradiancePipeline);
|
|
|
|
VkDescriptorImageInfo imageInfo = RHIDescriptorImageInfoStorage(irradianceMap->getImage().getView(irradianceViewRange, VK_IMAGE_VIEW_TYPE_CUBE));
|
|
std::vector<VkWriteDescriptorSet> writes
|
|
{
|
|
RHIPushWriteDescriptorSetImage(0, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &imageInfo),
|
|
RHIPushWriteDescriptorSetImage(1, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, &hdrCubeInfo),
|
|
};
|
|
|
|
// Push owner set #0.
|
|
RHI::PushDescriptorSetKHR(cmd, VK_PIPELINE_BIND_POINT_COMPUTE, pass->irradiancePipelineLayout, 0, uint32_t(writes.size()), writes.data());
|
|
|
|
vkCmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_COMPUTE,
|
|
pass->irradiancePipelineLayout, 1,
|
|
(uint32_t)compPassSets.size(), compPassSets.data(),
|
|
0, nullptr
|
|
);
|
|
|
|
IBLIrradiancePushConst push
|
|
{
|
|
.convolutionSampleCount = 1024,
|
|
.updateFaceIndex = int(faceIndex),
|
|
};
|
|
vkCmdPushConstants(cmd, pass->irradiancePipelineLayout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(push), &push);
|
|
|
|
|
|
vkCmdDispatch(cmd,
|
|
irradianceMap->getImage().getExtent().width,
|
|
irradianceMap->getImage().getExtent().height,
|
|
1u
|
|
);
|
|
}
|
|
irradianceMap->getImage().transitionLayout(cmd, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, irradianceViewRange);
|
|
|
|
auto skyPrefilter = getSkyPrefilter();
|
|
// Prefilter
|
|
{
|
|
vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_COMPUTE, pass->prefilterPipeline);
|
|
|
|
vkCmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_COMPUTE,
|
|
pass->prefilterPipelineLayout, 1,
|
|
(uint32_t)compPassSets.size(), compPassSets.data(),
|
|
0, nullptr
|
|
);
|
|
|
|
const float deltaRoughness = 1.0f / std::max(float(skyPrefilter->getImage().getInfo().mipLevels), 1.0f);
|
|
|
|
for (uint32_t i = 0; i < skyPrefilter->getImage().getInfo().mipLevels; i++)
|
|
{
|
|
auto viewRange = VkImageSubresourceRange
|
|
{
|
|
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
|
.baseMipLevel = i,
|
|
.levelCount = 1,
|
|
.baseArrayLayer = 0,
|
|
.layerCount = 6
|
|
};
|
|
|
|
skyPrefilter->getImage().transitionLayout(cmd, VK_IMAGE_LAYOUT_GENERAL, viewRange);
|
|
{
|
|
VkDescriptorImageInfo imageInfo = RHIDescriptorImageInfoStorage(skyPrefilter->getImage().getView(viewRange, VK_IMAGE_VIEW_TYPE_CUBE));
|
|
|
|
std::vector<VkWriteDescriptorSet> writes
|
|
{
|
|
RHIPushWriteDescriptorSetImage(0, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &imageInfo),
|
|
RHIPushWriteDescriptorSetImage(1, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, &hdrCubeInfo),
|
|
};
|
|
|
|
// Push owner set #0.
|
|
RHI::PushDescriptorSetKHR(cmd, VK_PIPELINE_BIND_POINT_COMPUTE, pass->prefilterPipelineLayout, 0, uint32_t(writes.size()), writes.data());
|
|
|
|
IBLPrefilterPushConst push
|
|
{
|
|
.perceptualRoughness = float(i) * deltaRoughness,
|
|
.samplesCount = 512,
|
|
.maxBrightValue = 10000.0f,
|
|
.filterRoughnessMin = 0.05f, // Realtime filter all roughness.
|
|
.updateFaceIndex = int(faceIndex),
|
|
};
|
|
vkCmdPushConstants(cmd, pass->prefilterPipelineLayout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(push), &push);
|
|
|
|
vkCmdDispatch(cmd,
|
|
glm::max(1u, skyPrefilter->getImage().getExtent().width >> i),
|
|
glm::max(1u, skyPrefilter->getImage().getExtent().height >> i),
|
|
1u);
|
|
}
|
|
skyPrefilter->getImage().transitionLayout(cmd, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, viewRange);
|
|
}
|
|
}
|
|
|
|
|
|
irradianceMap->getImage().transitionLayout(cmd, VK_IMAGE_LAYOUT_GENERAL, inCubeViewRangeAll);
|
|
irradianceMap->getImage().transitionLayout(cmd, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, inCubeViewRangeAll);
|
|
skyPrefilter->getImage().transitionLayout(cmd, VK_IMAGE_LAYOUT_GENERAL, inCubeViewRangeAll);
|
|
skyPrefilter->getImage().transitionLayout(cmd, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, inCubeViewRangeAll);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
namespace blueNoise_16_Spp
|
|
{
|
|
// blue noise sampler 16spp.
|
|
#include <samplerCPP/samplerBlueNoiseErrorDistribution_128x128_OptimizedFor_2d2d2d2d_16spp.cpp>
|
|
}
|
|
|
|
namespace blueNoise_8_Spp
|
|
{
|
|
// blue noise sampler 8spp.
|
|
#include <samplerCPP/samplerBlueNoiseErrorDistribution_128x128_OptimizedFor_2d2d2d2d_8spp.cpp>
|
|
}
|
|
|
|
namespace blueNoise_4_Spp
|
|
{
|
|
// blue noise sampler 4spp.
|
|
#include <samplerCPP/samplerBlueNoiseErrorDistribution_128x128_OptimizedFor_2d2d2d2d_4spp.cpp>
|
|
}
|
|
|
|
namespace blueNoise_2_Spp
|
|
{
|
|
// blue noise sampler 2spp.
|
|
#include <samplerCPP/samplerBlueNoiseErrorDistribution_128x128_OptimizedFor_2d2d2d2d_2spp.cpp>
|
|
}
|
|
|
|
namespace blueNoise_1_Spp
|
|
{
|
|
// blue noise sampler 1spp.
|
|
#include <samplerCPP/samplerBlueNoiseErrorDistribution_128x128_OptimizedFor_2d2d2d2d_1spp.cpp>
|
|
}
|
|
|
|
void GlobalBlueNoise::init()
|
|
{
|
|
auto buildBuffer = [](const char* name, void* ptr, VkDeviceSize size)
|
|
{
|
|
return VulkanBuffer::create(
|
|
name,
|
|
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
|
|
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
|
|
EVMAUsageFlags::StageCopyForUpload,
|
|
size,
|
|
ptr
|
|
);
|
|
};
|
|
|
|
#define WORK_CODE \
|
|
{\
|
|
BlueNoiseWorkingBuffer.sobolBuffer = buildBuffer(BlueNoiseWorkingName, (void*)BlueNoiseWorkingSpace::sobol_256spp_256d, sizeof(BlueNoiseWorkingSpace::sobol_256spp_256d));\
|
|
BlueNoiseWorkingBuffer.rankingTileBuffer = buildBuffer(BlueNoiseWorkingName, (void*)BlueNoiseWorkingSpace::rankingTile, sizeof(BlueNoiseWorkingSpace::rankingTile));\
|
|
BlueNoiseWorkingBuffer.scramblingTileBuffer = buildBuffer(BlueNoiseWorkingName, (void*)BlueNoiseWorkingSpace::scramblingTile, sizeof(BlueNoiseWorkingSpace::scramblingTile));\
|
|
BlueNoiseWorkingBuffer.buildSet();\
|
|
}
|
|
|
|
|
|
#define BlueNoiseWorkingBuffer spp_1_buffer
|
|
#define BlueNoiseWorkingSpace blueNoise_1_Spp
|
|
#define BlueNoiseWorkingName "Sobel_1_spp_buffer"
|
|
WORK_CODE
|
|
#undef BlueNoiseWorkingBuffer
|
|
#undef BlueNoiseWorkingSpace
|
|
#undef BlueNoiseWorkingName
|
|
|
|
|
|
#define BlueNoiseWorkingBuffer spp_2_buffer
|
|
#define BlueNoiseWorkingSpace blueNoise_2_Spp
|
|
#define BlueNoiseWorkingName "Sobel_2_spp_buffer"
|
|
WORK_CODE
|
|
#undef BlueNoiseWorkingBuffer
|
|
#undef BlueNoiseWorkingSpace
|
|
#undef BlueNoiseWorkingName
|
|
|
|
#define BlueNoiseWorkingBuffer spp_4_buffer
|
|
#define BlueNoiseWorkingSpace blueNoise_4_Spp
|
|
#define BlueNoiseWorkingName "Sobel_4_spp_buffer"
|
|
WORK_CODE
|
|
#undef BlueNoiseWorkingBuffer
|
|
#undef BlueNoiseWorkingSpace
|
|
#undef BlueNoiseWorkingName
|
|
|
|
#define BlueNoiseWorkingBuffer spp_8_buffer
|
|
#define BlueNoiseWorkingSpace blueNoise_8_Spp
|
|
#define BlueNoiseWorkingName "Sobel_8_spp_buffer"
|
|
WORK_CODE
|
|
#undef BlueNoiseWorkingBuffer
|
|
#undef BlueNoiseWorkingSpace
|
|
#undef BlueNoiseWorkingName
|
|
|
|
#define BlueNoiseWorkingBuffer spp_16_buffer
|
|
#define BlueNoiseWorkingSpace blueNoise_16_Spp
|
|
#define BlueNoiseWorkingName "Sobel_16_spp_buffer"
|
|
WORK_CODE
|
|
#undef BlueNoiseWorkingBuffer
|
|
#undef BlueNoiseWorkingSpace
|
|
#undef BlueNoiseWorkingName
|
|
|
|
#undef WORK_CODE
|
|
}
|
|
|
|
void GlobalBlueNoise::BufferMisc::buildSet()
|
|
{
|
|
VkDescriptorBufferInfo sobolInfo{};
|
|
sobolInfo.buffer = sobolBuffer->getVkBuffer();
|
|
sobolInfo.offset = 0;
|
|
sobolInfo.range = sobolBuffer->getSize();
|
|
|
|
VkDescriptorBufferInfo rankingTileInfo{};
|
|
rankingTileInfo.buffer = rankingTileBuffer->getVkBuffer();
|
|
rankingTileInfo.offset = 0;
|
|
rankingTileInfo.range = rankingTileBuffer->getSize();
|
|
|
|
VkDescriptorBufferInfo scramblingTileInfo{};
|
|
scramblingTileInfo.buffer = scramblingTileBuffer->getVkBuffer();
|
|
scramblingTileInfo.offset = 0;
|
|
scramblingTileInfo.range = scramblingTileBuffer->getSize();
|
|
|
|
RHI::get()->descriptorFactoryBegin()
|
|
.bindBuffers(0, 1, &sobolInfo, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
|
|
.bindBuffers(1, 1, &rankingTileInfo, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
|
|
.bindBuffers(2, 1, &scramblingTileInfo, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
|
|
.build(set, setLayouts);
|
|
}
|
|
|
|
} |