13using namespace Tempest;
16 return b.byteSize()<desiredSz || b.byteSize()>=2*desiredSz;
37 return bucketId==uint32_t(-1);
42 if(!opt.doMeshShading)
51 : owner(owner), buckets(buckets), clusters(clusters), scene(scene), vsmSupported(
Shaders::isVsmSupported()) {
57 Tempest::DispatchIndirectCommand cmd = {2000,1,1};
77void DrawCommands::setBindings(Tempest::Encoder<CommandBuffer>& cmd,
const DrawCmd& cx,
SceneGlobals::VisCamera v) {
80 const auto bId = cx.bucketId;
81 const auto& bx = cx.isBindless() ? nullBk : buckets.
buckets()[bId];
83 cmd.setBinding(L_Scene, scene.
uboGlobal[v]);
84 cmd.setBinding(L_Payload, views[v].visClusters);
86 cmd.setBinding(L_Bucket, buckets.
ssbo());
89 cmd.setBinding(L_Ibo, buckets.
ibo());
90 cmd.setBinding(L_Vbo, buckets.
vbo());
92 else if(bx.staticMesh!=
nullptr) {
93 cmd.setBinding(L_Ibo, bx.staticMesh->ibo8);
94 cmd.setBinding(L_Vbo, bx.staticMesh->vbo);
97 cmd.setBinding(L_Ibo, bx.animMesh->ibo8);
98 cmd.setBinding(L_Vbo, bx.animMesh->vbo);
102 if(cx.isBindless()) {
103 cmd.setBinding(L_Diffuse, buckets.
textures());
105 else if(bx.mat.hasFrameAnimation()) {
106 uint64_t timeShift = 0;
107 auto frame = size_t((timeShift+scene.
tickCount)/bx.mat.texAniFPSInv);
108 auto* t = bx.mat.frames[frame%bx.mat.frames.size()];
109 cmd.setBinding(L_Diffuse, *t);
112 cmd.setBinding(L_Diffuse, *bx.mat.tex);
115 cmd.setBinding(L_Sampler, smp);
123 if(cx.type==
Morph && cx.isBindless()) {
124 cmd.setBinding(L_MorphId, buckets.
morphId());
125 cmd.setBinding(L_Morph, buckets.
morph());
127 else if(cx.type==
Morph && bx.staticMesh!=
nullptr) {
128 cmd.setBinding(L_MorphId, *bx.staticMesh->morph.index);
129 cmd.setBinding(L_Morph, *bx.staticMesh->morph.samples);
133 cmd.setBinding(L_SceneClr, *scene.
sceneColor, Sampler::bilinear(ClampMode::MirroredRepeat));
134 cmd.setBinding(L_GDepth, *scene.
sceneDepth, Sampler::nearest (ClampMode::MirroredRepeat));
138 cmd.setBinding(L_CmdOffsets, views[v].indirectCmd);
140 cmd.setBinding(L_Lights, *scene.
lights);
152 if(pMain==
nullptr && pShadow==
nullptr && pHiZ==
nullptr)
155 for(
size_t i=0; i<cmd.size(); ++i) {
156 if(cmd[i].pMain!=pMain || cmd[i].pShadow!=pShadow || cmd[i].pHiZ!=pHiZ)
158 if(!bindless && cmd[i].bucketId!=bucketId)
163 auto ret = uint16_t(cmd.size());
170 cx.
bucketId = bindless ? 0xFFFFFFFF : bucketId;
173 cmd.push_back(std::move(cx));
180 cmd[cmdId].maxPayload += meshletCount;
197 ord.resize(cmd.size());
198 for(
size_t i=0; i<cmd.size(); ++i)
200 std::sort(ord.begin(), ord.end(), [](
const DrawCmd* l,
const DrawCmd* r){
201 return l->alpha < r->alpha;
204 size_t totalPayload = 0;
207 layChg |= (i.firstPayload != uint32_t(totalPayload));
208 i.firstPayload = uint32_t(totalPayload);
209 totalPayload += i.maxPayload;
212 totalPayload = (totalPayload + 0xFF) & ~
size_t(0xFF);
213 const size_t visClustersSz = totalPayload*
sizeof(uint32_t)*4;
216 bool cmdChg =
needtoReallocate(v.indirectCmd,
sizeof(IndirectCmd)*cmd.size());
218 this->maxPayload = totalPayload;
220 if(!layChg && !visChg) {
224 std::vector<IndirectCmd> cx(cmd.size());
225 for(
size_t i=0; i<cmd.size(); ++i) {
226 auto mesh = cmd[i].isMeshShader();
229 cx[i].writeOffset = cmd[i].firstPayload;
230 cx[i].firstVertex = mesh ? 1 : 0;
231 cx[i].firstInstance = mesh ? 1 : 0;
236 if(!isViewEnabled(v.viewport))
240 const size_t vsmMax = 1024*1024*4*4;
243 v.visClusters = device.ssbo(
nullptr, size);
247 v.vsmClusters = device.ssbo(
nullptr, v.visClusters.byteSize());
251 v.indirectCmd = device.ssbo(cx.data(),
sizeof(IndirectCmd)*cx.size());
254 auto staging = device.ssbo(BufferHeap::Upload, cx.data(),
sizeof(IndirectCmd)*cx.size());
256 enc.setBinding(0, v.indirectCmd);
257 enc.setBinding(1, staging);
259 enc.dispatchThreads(staging.byteSize()/
sizeof(uint32_t));
267 static bool freeze =
false;
271 cmd.setFramebuffer({});
274 if(this->cmd.empty())
276 if(!isViewEnabled(v.viewport))
278 const uint32_t isMeshShader = (
Gothic::options().doMeshShading ? 1 : 0);
279 cmd.setBinding(T_Indirect, v.indirectCmd);
280 cmd.setPushData(&isMeshShader,
sizeof(isMeshShader));
282 cmd.dispatchThreads(this->cmd.size());
294 if(!isViewEnabled(viewport))
297 struct Push { uint32_t firstMeshlet; uint32_t meshletCount;
float znear; } push = {};
298 push.firstMeshlet = 0;
299 push.meshletCount = uint32_t(clusters.
size());
300 push.znear = scene.
znear;
308 cmd.setBinding(T_Scene, scene.
uboGlobal[viewport]);
309 cmd.setBinding(T_Payload, views[viewport].visClusters);
311 cmd.setBinding(T_Bucket, buckets.
ssbo());
312 cmd.setBinding(T_Indirect, views[viewport].indirectCmd);
313 cmd.setBinding(T_Clusters, clusters.
ssbo());
314 cmd.setBinding(T_HiZ, *scene.
hiZ);
315 cmd.setPushData(push);
316 cmd.setPipeline(*pso);
317 cmd.dispatchThreads(push.meshletCount);
324 struct Push { uint32_t meshletCount; } push = {};
325 push.meshletCount = uint32_t(clusters.
size());
329 cmd.setBinding(T_Payload, view.vsmClusters);
331 cmd.setBinding(T_Bucket, buckets.
ssbo());
332 cmd.setBinding(T_Indirect, view.indirectCmd);
333 cmd.setBinding(T_Clusters, clusters.
ssbo());
334 cmd.setBinding(T_Lights, *scene.
lights);
337 cmd.setBinding(9, scene.
vsmDbg);
338 cmd.setPushData(&push,
sizeof(push));
339 cmd.setPipeline(shaders.vsmVisibilityPass);
340 cmd.dispatchThreads(push.meshletCount,
size_t(scene.
vsmPageTbl->d() + 1));
342 cmd.setBinding(1, view.vsmClusters);
343 cmd.setBinding(2, view.visClusters);
344 cmd.setBinding(3, view.indirectCmd);
346 cmd.setBinding(5, vsmIndirectCmd);
347 cmd.setPipeline(shaders.vsmPackDraw0);
350 cmd.setBinding(1, view.vsmClusters);
351 cmd.setBinding(2, view.visClusters);
352 cmd.setBinding(3, view.indirectCmd);
354 cmd.setPipeline(shaders.vsmPackDraw1);
361 struct Push { uint32_t commandId; } push = {};
364 auto& view = views[viewId];
366 for(
size_t i=0; i<ord.size(); ++i) {
373 auto id = size_t(std::distance(this->cmd.data(), &cx));
374 push.commandId = uint32_t(
id);
377 setBindings(cmd, cx, viewId);
378 cmd.setPushData(push);
379 cmd.setPipeline(*cx.pVsm);
380 if(cx.isMeshShader())
381 cmd.dispatchMeshIndirect(view.indirectCmd,
sizeof(IndirectCmd)*
id +
sizeof(uint32_t));
else
382 cmd.drawIndirect(view.indirectCmd,
sizeof(IndirectCmd)*
id);
386 struct Push { uint32_t meshletCount; } push = {};
387 push.meshletCount = uint32_t(clusters.
size());
389 cmd.setFramebuffer({});
393 cmd.setBinding(3, clusters.
ssbo());
395 cmd.setBinding(5, buckets.
ibo());
396 cmd.setBinding(6, buckets.
vbo());
397 cmd.setBinding(7, buckets.
textures());
398 cmd.setBinding(8, Sampler::bilinear());
399 cmd.setPushData(&push,
sizeof(push));
408 struct Push { uint32_t firstMeshlet; uint32_t meshletCount; } push = {};
411 auto& view = views[viewId];
413 for(
size_t i=0; i<ord.size(); ++i) {
422 auto id = size_t(std::distance(this->cmd.data(), &cx));
423 push.firstMeshlet = cx.firstPayload;
424 push.meshletCount = cx.maxPayload;
426 setBindings(cmd, cx, viewId);
427 cmd.setPushData(push);
428 cmd.setPipeline(*cx.pHiZ);
429 if(cx.isMeshShader())
430 cmd.dispatchMeshIndirect(view.indirectCmd,
sizeof(IndirectCmd)*
id +
sizeof(uint32_t));
else
431 cmd.drawIndirect(view.indirectCmd,
sizeof(IndirectCmd)*
id);
436 struct Push { uint32_t firstMeshlet; uint32_t meshletCount; } push = {};
445 auto& view = views[viewId];
446 for(
auto i=b; i!=e; ++i) {
454 const RenderPipeline* pso =
nullptr;
471 auto id = size_t(std::distance(this->cmd.data(), &cx));
472 push.firstMeshlet = cx.firstPayload;
473 push.meshletCount = cx.maxPayload;
475 setBindings(cmd, cx, viewId);
476 cmd.setPushData(push);
477 cmd.setPipeline(*pso);
478 if(cx.isMeshShader())
479 cmd.dispatchMeshIndirect(view.indirectCmd,
sizeof(IndirectCmd)*
id +
sizeof(uint32_t));
else
480 cmd.drawIndirect(view.indirectCmd,
sizeof(IndirectCmd)*
id);
Tempest::DescriptorArray ibo
Tempest::DescriptorArray morphId
auto buckets() -> const std::vector< Bucket > &
auto ssbo() const -> const Tempest::StorageBuffer &
Tempest::DescriptorArray vbo
Tempest::DescriptorArray morph
auto ssbo() -> Tempest::StorageBuffer &
void addClusters(uint16_t cmdId, uint32_t meshletCount)
void visibilityVsm(Tempest::Encoder< Tempest::CommandBuffer > &cmd)
DrawCommands(VisualObjects &owner, DrawBuckets &buckets, DrawClusters &clusters, const SceneGlobals &scene)
uint16_t commandId(const Material &m, Type type, uint32_t bucketId)
void drawVsm(Tempest::Encoder< Tempest::CommandBuffer > &cmd)
void drawHiZ(Tempest::Encoder< Tempest::CommandBuffer > &cmd)
void commit(Tempest::Encoder< Tempest::CommandBuffer > &cmd)
void drawCommon(Tempest::Encoder< Tempest::CommandBuffer > &cmd, SceneGlobals::VisCamera viewId, Material::AlphaFunc func)
void visibilityPass(Tempest::Encoder< Tempest::CommandBuffer > &cmd, int pass)
static auto options() -> const Options &
bool isShadowmapRequired() const
bool isForwardShading() const
bool isTextureInShadowPass() const
bool isTesselated() const
bool hasFrameAnimation() const
bool isSceneInfoRequired() const
static const Tempest::Sampler & shadowSampler()
static Tempest::Device & device()
static void recycle(Tempest::DescriptorArray &&arr)
const Tempest::StorageBuffer * vsmPageList
const Tempest::Texture2d * shadowMap[2]
Tempest::StorageImage vsmDbg
Tempest::StorageBuffer uboGlobal[V_Count]
const Tempest::Texture2d * sceneColor
const Tempest::Texture2d * hiZ
const Tempest::StorageImage * vsmPageTbl
const Tempest::Texture2d * vsmPageData
static bool isShadowView(VisCamera v)
const Tempest::StorageBuffer * lights
const Tempest::StorageImage * vsmPageHiZ
const Tempest::Texture2d * sceneDepth
const Tempest::RenderPipeline * materialPipeline(const Material &desc, DrawCommands::Type t, PipelineType pt, bool bindless) const
Tempest::ComputePipeline visibilityPassSh
Tempest::ComputePipeline visibilityPassHiZCr
Tempest::ComputePipeline visibilityPassHiZ
Tempest::ComputePipeline clusterInit
auto instanceSsbo() const -> const Tempest::StorageBuffer &
static bool needtoReallocate(const StorageBuffer &b, const size_t desiredSz)
bool isSceneInfoRequired() const
const Tempest::RenderPipeline * pShadow
bool isTextureInShadowPass() const
const Tempest::RenderPipeline * pMain
const Tempest::RenderPipeline * pHiZ
bool isMeshShader() const
bool isShadowmapRequired() const
const Tempest::RenderPipeline * pVsm
Material::AlphaFunc alpha
bool isForwardShading() const