|
|
@@ -98,7 +98,7 @@ Error RtShadows::initInternal()
|
|
|
{
|
|
|
TextureInitInfo texinit = getRenderer().create2DRenderTargetInitInfo(
|
|
|
getRenderer().getInternalResolution().x() / 2, getRenderer().getInternalResolution().y() / 2, Format::kR8_Unorm,
|
|
|
- TextureUsageBit::kAllSampled | TextureUsageBit::kUavTraceRaysWrite | TextureUsageBit::kUavComputeWrite, "RtShadows History");
|
|
|
+ TextureUsageBit::kAllSampled | TextureUsageBit::kStorageTraceRaysWrite | TextureUsageBit::kStorageComputeWrite, "RtShadows History");
|
|
|
m_historyRt = getRenderer().createAndClearRenderTarget(texinit, TextureUsageBit::kSampledFragment);
|
|
|
}
|
|
|
|
|
|
@@ -113,7 +113,7 @@ Error RtShadows::initInternal()
|
|
|
{
|
|
|
TextureInitInfo texinit = getRenderer().create2DRenderTargetInitInfo(
|
|
|
getRenderer().getInternalResolution().x() / 2, getRenderer().getInternalResolution().y() / 2, Format::kR32G32_Sfloat,
|
|
|
- TextureUsageBit::kAllSampled | TextureUsageBit::kUavTraceRaysWrite | TextureUsageBit::kUavComputeWrite, "RtShadows Moments #1");
|
|
|
+ TextureUsageBit::kAllSampled | TextureUsageBit::kStorageTraceRaysWrite | TextureUsageBit::kStorageComputeWrite, "RtShadows Moments #1");
|
|
|
m_momentsRts[0] = getRenderer().createAndClearRenderTarget(texinit, TextureUsageBit::kSampledFragment);
|
|
|
|
|
|
texinit.setName("RtShadows Moments #2");
|
|
|
@@ -138,7 +138,7 @@ Error RtShadows::initInternal()
|
|
|
{
|
|
|
TextureInitInfo texinit = getRenderer().create2DRenderTargetInitInfo(
|
|
|
getRenderer().getInternalResolution().x() / 2, getRenderer().getInternalResolution().y() / 2, Format::kR32_Sfloat,
|
|
|
- TextureUsageBit::kAllSampled | TextureUsageBit::kUavTraceRaysWrite | TextureUsageBit::kUavComputeWrite, "RtShadows history len");
|
|
|
+ TextureUsageBit::kAllSampled | TextureUsageBit::kStorageTraceRaysWrite | TextureUsageBit::kStorageComputeWrite, "RtShadows history len");
|
|
|
ClearValue clear;
|
|
|
clear.m_colorf[0] = 1.0f;
|
|
|
m_dummyHistoryLenTex = getRenderer().createAndClearRenderTarget(texinit, TextureUsageBit::kSampledFragment, clear);
|
|
|
@@ -212,7 +212,7 @@ void RtShadows::populateRenderGraph(RenderingContext& ctx)
|
|
|
BufferOffsetRange sbtBuildIndirectArgsBuffer;
|
|
|
{
|
|
|
sbtBuildIndirectArgsBuffer = GpuVisibleTransientMemoryPool::getSingleton().allocate(sizeof(DispatchIndirectArgs));
|
|
|
- sbtBuildIndirectArgsHandle = rgraph.importBuffer(BufferUsageBit::kUavComputeWrite, sbtBuildIndirectArgsBuffer);
|
|
|
+ sbtBuildIndirectArgsHandle = rgraph.importBuffer(BufferUsageBit::kStorageComputeWrite, sbtBuildIndirectArgsBuffer);
|
|
|
|
|
|
ComputeRenderPassDescription& rpass = rgraph.newComputeRenderPass("RtShadows setup build SBT");
|
|
|
|
|
|
@@ -224,8 +224,8 @@ void RtShadows::populateRenderGraph(RenderingContext& ctx)
|
|
|
|
|
|
cmdb.bindShaderProgram(m_setupBuildSbtGrProg.get());
|
|
|
|
|
|
- cmdb.bindUavBuffer(0, 0, GpuSceneArrays::RenderableBoundingVolumeRt::getSingleton().getBufferOffsetRange());
|
|
|
- cmdb.bindUavBuffer(0, 1, sbtBuildIndirectArgsBuffer);
|
|
|
+ cmdb.bindStorageBuffer(0, 0, GpuSceneArrays::RenderableBoundingVolumeRt::getSingleton().getBufferOffsetRange());
|
|
|
+ cmdb.bindStorageBuffer(0, 1, sbtBuildIndirectArgsBuffer);
|
|
|
|
|
|
cmdb.dispatchCompute(1, 1, 1);
|
|
|
});
|
|
|
@@ -239,7 +239,7 @@ void RtShadows::populateRenderGraph(RenderingContext& ctx)
|
|
|
U8* sbtMem;
|
|
|
sbtBuffer = RebarTransientMemoryPool::getSingleton().allocateFrame(
|
|
|
(GpuSceneArrays::RenderableBoundingVolumeRt::getSingleton().getElementCount() + 2) * m_sbtRecordSize, sbtMem);
|
|
|
- sbtHandle = rgraph.importBuffer(BufferUsageBit::kUavComputeWrite, sbtBuffer);
|
|
|
+ sbtHandle = rgraph.importBuffer(BufferUsageBit::kStorageComputeWrite, sbtBuffer);
|
|
|
|
|
|
// Write the first 2 entries of the SBT
|
|
|
ConstWeakArray<U8> shaderGroupHandles = m_rtLibraryGrProg->getShaderGroupHandles();
|
|
|
@@ -254,7 +254,7 @@ void RtShadows::populateRenderGraph(RenderingContext& ctx)
|
|
|
BufferOffsetRange visibleRenderableIndicesBuff;
|
|
|
getRenderer().getAccelerationStructureBuilder().getVisibilityInfo(visibilityHandle, visibleRenderableIndicesBuff);
|
|
|
|
|
|
- rpass.newBufferDependency(visibilityHandle, BufferUsageBit::kUavComputeRead);
|
|
|
+ rpass.newBufferDependency(visibilityHandle, BufferUsageBit::kStorageComputeRead);
|
|
|
rpass.newBufferDependency(sbtBuildIndirectArgsHandle, BufferUsageBit::kIndirectCompute);
|
|
|
|
|
|
rpass.setWork([this, sbtBuildIndirectArgsBuffer, sbtBuffer, visibleRenderableIndicesBuff](RenderPassWorkContext& rgraphCtx) {
|
|
|
@@ -263,13 +263,13 @@ void RtShadows::populateRenderGraph(RenderingContext& ctx)
|
|
|
|
|
|
cmdb.bindShaderProgram(m_buildSbtGrProg.get());
|
|
|
|
|
|
- cmdb.bindUavBuffer(0, 0, GpuSceneArrays::Renderable::getSingleton().getBufferOffsetRange());
|
|
|
- cmdb.bindUavBuffer(0, 1, &GpuSceneBuffer::getSingleton().getBuffer(), 0, kMaxPtrSize);
|
|
|
- cmdb.bindUavBuffer(0, 2, visibleRenderableIndicesBuff);
|
|
|
- cmdb.bindUavBuffer(0, 3, &m_rtLibraryGrProg->getShaderGroupHandlesGpuBuffer(), 0, kMaxPtrSize);
|
|
|
- cmdb.bindUavBuffer(0, 4, sbtBuffer);
|
|
|
+ cmdb.bindStorageBuffer(0, 0, GpuSceneArrays::Renderable::getSingleton().getBufferOffsetRange());
|
|
|
+ cmdb.bindStorageBuffer(0, 1, &GpuSceneBuffer::getSingleton().getBuffer(), 0, kMaxPtrSize);
|
|
|
+ cmdb.bindStorageBuffer(0, 2, visibleRenderableIndicesBuff);
|
|
|
+ cmdb.bindStorageBuffer(0, 3, &m_rtLibraryGrProg->getShaderGroupHandlesGpuBuffer(), 0, kMaxPtrSize);
|
|
|
+ cmdb.bindStorageBuffer(0, 4, sbtBuffer);
|
|
|
|
|
|
- RtShadowsSbtBuildConstants unis = {};
|
|
|
+ RtShadowsSbtBuildUniforms unis = {};
|
|
|
ANKI_ASSERT(m_sbtRecordSize % 4 == 0);
|
|
|
unis.m_sbtRecordDwordSize = m_sbtRecordSize / 4;
|
|
|
const U32 shaderHandleSize = GrManager::getSingleton().getDeviceCapabilities().m_shaderGroupHandleSize;
|
|
|
@@ -286,7 +286,7 @@ void RtShadows::populateRenderGraph(RenderingContext& ctx)
|
|
|
ComputeRenderPassDescription& rpass = rgraph.newComputeRenderPass("RtShadows");
|
|
|
|
|
|
rpass.newTextureDependency(m_runCtx.m_historyRt, TextureUsageBit::kSampledTraceRays);
|
|
|
- rpass.newTextureDependency(m_runCtx.m_intermediateShadowsRts[0], TextureUsageBit::kUavTraceRaysWrite);
|
|
|
+ rpass.newTextureDependency(m_runCtx.m_intermediateShadowsRts[0], TextureUsageBit::kStorageTraceRaysWrite);
|
|
|
rpass.newAccelerationStructureDependency(getRenderer().getAccelerationStructureBuilder().getAccelerationStructureHandle(),
|
|
|
AccelerationStructureUsageBit::kTraceRaysRead);
|
|
|
rpass.newTextureDependency(ANKI_DEPTH_DEP);
|
|
|
@@ -294,9 +294,9 @@ void RtShadows::populateRenderGraph(RenderingContext& ctx)
|
|
|
rpass.newTextureDependency(getRenderer().getGBuffer().getColorRt(2), TextureUsageBit::kSampledTraceRays);
|
|
|
|
|
|
rpass.newTextureDependency(m_runCtx.m_prevMomentsRt, TextureUsageBit::kSampledTraceRays);
|
|
|
- rpass.newTextureDependency(m_runCtx.m_currentMomentsRt, TextureUsageBit::kUavTraceRaysWrite);
|
|
|
+ rpass.newTextureDependency(m_runCtx.m_currentMomentsRt, TextureUsageBit::kStorageTraceRaysWrite);
|
|
|
|
|
|
- rpass.newBufferDependency(getRenderer().getClusterBinning().getClustersBufferHandle(), BufferUsageBit::kUavTraceRaysRead);
|
|
|
+ rpass.newBufferDependency(getRenderer().getClusterBinning().getClustersBufferHandle(), BufferUsageBit::kStorageTraceRaysRead);
|
|
|
|
|
|
rpass.setWork([this, sbtBuffer, &ctx](RenderPassWorkContext& rgraphCtx) {
|
|
|
ANKI_TRACE_SCOPED_EVENT(RtShadows);
|
|
|
@@ -306,34 +306,34 @@ void RtShadows::populateRenderGraph(RenderingContext& ctx)
|
|
|
|
|
|
// Allocate, set and bind global uniforms
|
|
|
{
|
|
|
- MaterialGlobalConstants* globalUniforms;
|
|
|
+ MaterialGlobalUniforms* globalUniforms;
|
|
|
const RebarAllocation globalUniformsToken = RebarTransientMemoryPool::getSingleton().allocateFrame(1, globalUniforms);
|
|
|
|
|
|
memset(globalUniforms, 0, sizeof(*globalUniforms)); // Don't care for now
|
|
|
|
|
|
- cmdb.bindConstantBuffer(U32(MaterialSet::kGlobal), U32(MaterialBinding::kGlobalConstants), globalUniformsToken);
|
|
|
+ cmdb.bindUniformBuffer(U32(MaterialSet::kGlobal), U32(MaterialBinding::kGlobalUniforms), globalUniformsToken);
|
|
|
}
|
|
|
|
|
|
// More globals
|
|
|
cmdb.bindAllBindless(U32(MaterialSet::kBindless));
|
|
|
cmdb.bindSampler(U32(MaterialSet::kGlobal), U32(MaterialBinding::kTrilinearRepeatSampler),
|
|
|
getRenderer().getSamplers().m_trilinearRepeat.get());
|
|
|
- cmdb.bindUavBuffer(U32(MaterialSet::kGlobal), U32(MaterialBinding::kGpuScene), &GpuSceneBuffer::getSingleton().getBuffer(), 0,
|
|
|
- kMaxPtrSize);
|
|
|
+ cmdb.bindStorageBuffer(U32(MaterialSet::kGlobal), U32(MaterialBinding::kGpuScene), &GpuSceneBuffer::getSingleton().getBuffer(), 0,
|
|
|
+ kMaxPtrSize);
|
|
|
|
|
|
#define ANKI_UNIFIED_GEOM_FORMAT(fmt, shaderType) \
|
|
|
- cmdb.bindReadOnlyTextureBuffer(U32(MaterialSet::kGlobal), U32(MaterialBinding::kUnifiedGeometry_##fmt), \
|
|
|
- &UnifiedGeometryBuffer::getSingleton().getBuffer(), 0, kMaxPtrSize, Format::k##fmt);
|
|
|
+ cmdb.bindReadOnlyTexelBuffer(U32(MaterialSet::kGlobal), U32(MaterialBinding::kUnifiedGeometry_##fmt), \
|
|
|
+ &UnifiedGeometryBuffer::getSingleton().getBuffer(), 0, kMaxPtrSize, Format::k##fmt);
|
|
|
#include <AnKi/Shaders/Include/UnifiedGeometryTypes.def.h>
|
|
|
|
|
|
constexpr U32 kSet = 2;
|
|
|
|
|
|
- cmdb.bindConstantBuffer(kSet, 0, ctx.m_globalRenderingConstsBuffer);
|
|
|
- cmdb.bindUavBuffer(kSet, 1, getRenderer().getClusterBinning().getClustersBuffer());
|
|
|
+ cmdb.bindUniformBuffer(kSet, 0, ctx.m_globalRenderingUniformsBuffer);
|
|
|
+ cmdb.bindStorageBuffer(kSet, 1, getRenderer().getClusterBinning().getClustersBuffer());
|
|
|
|
|
|
cmdb.bindSampler(kSet, 2, getRenderer().getSamplers().m_trilinearRepeat.get());
|
|
|
|
|
|
- rgraphCtx.bindUavTexture(kSet, 3, m_runCtx.m_intermediateShadowsRts[0]);
|
|
|
+ rgraphCtx.bindStorageTexture(kSet, 3, m_runCtx.m_intermediateShadowsRts[0]);
|
|
|
rgraphCtx.bindColorTexture(kSet, 4, m_runCtx.m_historyRt);
|
|
|
cmdb.bindSampler(kSet, 5, getRenderer().getSamplers().m_trilinearClamp.get());
|
|
|
rgraphCtx.bindTexture(kSet, 6, getRenderer().getDepthDownscale().getRt(), DepthDownscale::kQuarterInternalResolution);
|
|
|
@@ -342,7 +342,7 @@ void RtShadows::populateRenderGraph(RenderingContext& ctx)
|
|
|
rgraphCtx.bindColorTexture(kSet, 9, getRenderer().getGBuffer().getColorRt(2));
|
|
|
rgraphCtx.bindAccelerationStructure(kSet, 10, getRenderer().getAccelerationStructureBuilder().getAccelerationStructureHandle());
|
|
|
rgraphCtx.bindColorTexture(kSet, 11, m_runCtx.m_prevMomentsRt);
|
|
|
- rgraphCtx.bindUavTexture(kSet, 12, m_runCtx.m_currentMomentsRt);
|
|
|
+ rgraphCtx.bindStorageTexture(kSet, 12, m_runCtx.m_currentMomentsRt);
|
|
|
cmdb.bindTexture(kSet, 13, &m_blueNoiseImage->getTextureView());
|
|
|
|
|
|
cmdb.traceRays(sbtBuffer.m_buffer, sbtBuffer.m_offset, m_sbtRecordSize,
|
|
|
@@ -365,7 +365,7 @@ void RtShadows::populateRenderGraph(RenderingContext& ctx)
|
|
|
rpass.newTextureDependency(getRenderer().getGBuffer().getColorRt(2), TextureUsageBit::kSampledCompute);
|
|
|
rpass.newTextureDependency(m_runCtx.m_currentMomentsRt, TextureUsageBit::kSampledCompute);
|
|
|
|
|
|
- rpass.newTextureDependency(m_runCtx.m_intermediateShadowsRts[1], TextureUsageBit::kUavComputeWrite);
|
|
|
+ rpass.newTextureDependency(m_runCtx.m_intermediateShadowsRts[1], TextureUsageBit::kStorageComputeWrite);
|
|
|
}
|
|
|
|
|
|
// Denoise pass vertical
|
|
|
@@ -381,7 +381,7 @@ void RtShadows::populateRenderGraph(RenderingContext& ctx)
|
|
|
rpass.newTextureDependency(getRenderer().getGBuffer().getColorRt(2), TextureUsageBit::kSampledCompute);
|
|
|
rpass.newTextureDependency(m_runCtx.m_currentMomentsRt, TextureUsageBit::kSampledCompute);
|
|
|
|
|
|
- rpass.newTextureDependency(m_runCtx.m_historyRt, TextureUsageBit::kUavComputeWrite);
|
|
|
+ rpass.newTextureDependency(m_runCtx.m_historyRt, TextureUsageBit::kStorageComputeWrite);
|
|
|
}
|
|
|
|
|
|
// Variance calculation pass
|
|
|
@@ -394,8 +394,8 @@ void RtShadows::populateRenderGraph(RenderingContext& ctx)
|
|
|
rpass.newTextureDependency(ANKI_DEPTH_DEP);
|
|
|
rpass.newTextureDependency(getRenderer().getGBuffer().getColorRt(2), TextureUsageBit::kSampledCompute);
|
|
|
|
|
|
- rpass.newTextureDependency(m_runCtx.m_intermediateShadowsRts[1], TextureUsageBit::kUavComputeWrite);
|
|
|
- rpass.newTextureDependency(m_runCtx.m_varianceRts[1], TextureUsageBit::kUavComputeWrite);
|
|
|
+ rpass.newTextureDependency(m_runCtx.m_intermediateShadowsRts[1], TextureUsageBit::kStorageComputeWrite);
|
|
|
+ rpass.newTextureDependency(m_runCtx.m_varianceRts[1], TextureUsageBit::kStorageComputeWrite);
|
|
|
|
|
|
rpass.setWork([this, &ctx](RenderPassWorkContext& rgraphCtx) {
|
|
|
ANKI_TRACE_SCOPED_EVENT(RtShadows);
|
|
|
@@ -410,8 +410,8 @@ void RtShadows::populateRenderGraph(RenderingContext& ctx)
|
|
|
cmdb.bindTexture(0, 3, m_dummyHistoryLenTexView.get());
|
|
|
rgraphCtx.bindTexture(0, 4, getRenderer().getDepthDownscale().getRt(), DepthDownscale::kQuarterInternalResolution);
|
|
|
|
|
|
- rgraphCtx.bindUavTexture(0, 5, m_runCtx.m_intermediateShadowsRts[1]);
|
|
|
- rgraphCtx.bindUavTexture(0, 6, m_runCtx.m_varianceRts[1]);
|
|
|
+ rgraphCtx.bindStorageTexture(0, 5, m_runCtx.m_intermediateShadowsRts[1]);
|
|
|
+ rgraphCtx.bindStorageTexture(0, 6, m_runCtx.m_varianceRts[1]);
|
|
|
|
|
|
const Mat4& invProjMat = ctx.m_matrices.m_projectionJitter.getInverse();
|
|
|
cmdb.setPushConstants(&invProjMat, sizeof(invProjMat));
|
|
|
@@ -437,13 +437,13 @@ void RtShadows::populateRenderGraph(RenderingContext& ctx)
|
|
|
|
|
|
if(!lastPass)
|
|
|
{
|
|
|
- rpass.newTextureDependency(m_runCtx.m_intermediateShadowsRts[!readRtIdx], TextureUsageBit::kUavComputeWrite);
|
|
|
+ rpass.newTextureDependency(m_runCtx.m_intermediateShadowsRts[!readRtIdx], TextureUsageBit::kStorageComputeWrite);
|
|
|
|
|
|
- rpass.newTextureDependency(m_runCtx.m_varianceRts[!readRtIdx], TextureUsageBit::kUavComputeWrite);
|
|
|
+ rpass.newTextureDependency(m_runCtx.m_varianceRts[!readRtIdx], TextureUsageBit::kStorageComputeWrite);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- rpass.newTextureDependency(m_runCtx.m_historyRt, TextureUsageBit::kUavComputeWrite);
|
|
|
+ rpass.newTextureDependency(m_runCtx.m_historyRt, TextureUsageBit::kStorageComputeWrite);
|
|
|
}
|
|
|
|
|
|
rpass.setWork([this, &ctx, passIdx = i](RenderPassWorkContext& rgraphCtx) {
|
|
|
@@ -471,12 +471,12 @@ void RtShadows::populateRenderGraph(RenderingContext& ctx)
|
|
|
|
|
|
if(!lastPass)
|
|
|
{
|
|
|
- rgraphCtx.bindUavTexture(0, 5, m_runCtx.m_intermediateShadowsRts[!readRtIdx]);
|
|
|
- rgraphCtx.bindUavTexture(0, 6, m_runCtx.m_varianceRts[!readRtIdx]);
|
|
|
+ rgraphCtx.bindStorageTexture(0, 5, m_runCtx.m_intermediateShadowsRts[!readRtIdx]);
|
|
|
+ rgraphCtx.bindStorageTexture(0, 6, m_runCtx.m_varianceRts[!readRtIdx]);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- rgraphCtx.bindUavTexture(0, 5, m_runCtx.m_historyRt);
|
|
|
+ rgraphCtx.bindStorageTexture(0, 5, m_runCtx.m_historyRt);
|
|
|
}
|
|
|
|
|
|
const Mat4& invProjMat = ctx.m_matrices.m_projectionJitter.getInverse();
|
|
|
@@ -495,7 +495,7 @@ void RtShadows::populateRenderGraph(RenderingContext& ctx)
|
|
|
rpass.newTextureDependency(getRenderer().getGBuffer().getDepthRt(), TextureUsageBit::kSampledCompute);
|
|
|
rpass.newTextureDependency(ANKI_DEPTH_DEP);
|
|
|
|
|
|
- rpass.newTextureDependency(m_runCtx.m_upscaledRt, TextureUsageBit::kUavComputeWrite);
|
|
|
+ rpass.newTextureDependency(m_runCtx.m_upscaledRt, TextureUsageBit::kStorageComputeWrite);
|
|
|
|
|
|
rpass.setWork([this](RenderPassWorkContext& rgraphCtx) {
|
|
|
ANKI_TRACE_SCOPED_EVENT(RtShadows);
|
|
|
@@ -506,7 +506,7 @@ void RtShadows::populateRenderGraph(RenderingContext& ctx)
|
|
|
cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_trilinearClamp.get());
|
|
|
|
|
|
rgraphCtx.bindColorTexture(0, 1, m_runCtx.m_historyRt);
|
|
|
- rgraphCtx.bindUavTexture(0, 2, m_runCtx.m_upscaledRt);
|
|
|
+ rgraphCtx.bindStorageTexture(0, 2, m_runCtx.m_upscaledRt);
|
|
|
rgraphCtx.bindTexture(0, 3, getRenderer().getDepthDownscale().getRt(), DepthDownscale::kQuarterInternalResolution);
|
|
|
rgraphCtx.bindTexture(0, 4, getRenderer().getGBuffer().getDepthRt(), TextureSubresourceInfo(DepthStencilAspectBit::kDepth));
|
|
|
|
|
|
@@ -529,9 +529,9 @@ void RtShadows::runDenoise(const RenderingContext& ctx, RenderPassWorkContext& r
|
|
|
rgraphCtx.bindColorTexture(0, 4, m_runCtx.m_currentMomentsRt);
|
|
|
cmdb.bindTexture(0, 5, m_dummyHistoryLenTexView.get());
|
|
|
|
|
|
- rgraphCtx.bindUavTexture(0, 6, (horizontal) ? m_runCtx.m_intermediateShadowsRts[1] : m_runCtx.m_historyRt);
|
|
|
+ rgraphCtx.bindStorageTexture(0, 6, (horizontal) ? m_runCtx.m_intermediateShadowsRts[1] : m_runCtx.m_historyRt);
|
|
|
|
|
|
- RtShadowsDenoiseConstants consts;
|
|
|
+ RtShadowsDenoiseUniforms consts;
|
|
|
consts.m_invViewProjMat = ctx.m_matrices.m_invertedViewProjectionJitter;
|
|
|
consts.m_time = F32(GlobalFrameIndex::getSingleton().m_value % 0xFFFFu);
|
|
|
consts.m_minSampleCount = 8;
|