Adding basic CBT Terrain implementation

This commit is contained in:
Dynamitos
2024-10-10 20:36:59 +02:00
parent c89fd405b8
commit 98a7e16756
38 changed files with 3779 additions and 373 deletions
+58 -24
View File
@@ -22,6 +22,37 @@ using namespace Seele::Editor;
// make it global so it gets deleted last and automatically
static Gfx::OGraphics graphics;
struct Halfedge {
uint32 vertexID;
uint32 nextID;
uint32 prevID;
uint32 twinID;
};
Array<Halfedge> generateEdges() {
Array<UVector> indices = {UVector(0, 1, 4), UVector(4, 1, 5), UVector(1, 2, 5), UVector(5, 2, 6), UVector(2, 3, 6),
UVector(6, 3, 7), UVector(4, 5, 8), UVector(8, 5, 9), UVector(5, 6, 9), UVector(9, 6, 10),
UVector(6, 7, 10), UVector(10, 7, 11), UVector(8, 9, 12), UVector(12, 9, 13), UVector(9, 10, 13),
UVector(13, 10, 14), UVector(10, 11, 14), UVector(14, 11, 15)};
Array<Halfedge> edges;
for (auto ind : indices) {
uint32 baseIndex = edges.size();
edges.add(Halfedge{ind.x, baseIndex+1, baseIndex+2, UINT32_MAX});
edges.add(Halfedge{ind.y, baseIndex+2, baseIndex, UINT32_MAX});
edges.add(Halfedge{ind.z, baseIndex, baseIndex+1, UINT32_MAX});
}
for (uint32 i = 0; i < edges.size(); ++i) {
if (edges[i].twinID == UINT32_MAX) {
for (uint32 j = 0; j < edges.size(); ++j) {
if (edges[i].vertexID == edges[edges[j].nextID].vertexID && edges[edges[i].nextID].vertexID == edges[j].vertexID) {
edges[i].twinID = j;
edges[j].twinID = i;
}
}
}
}
return edges;
}
int main() {
std::string gameName = "MeshShadingDemo";
#ifdef WIN32
@@ -65,32 +96,35 @@ int main() {
.filePath = sourcePath / "import/textures/skyboxsun5deg_tn.jpg",
.type = TextureImportType::TEXTURE_CUBEMAP,
});
//AssetImporter::importMesh(MeshImportArgs{
// .filePath = sourcePath / "import/models/ship.fbx",
// .importPath = "ship",
//});
AssetImporter::importTexture(TextureImportArgs{
.filePath = sourcePath / "import/textures/azeroth.png",
});
AssetImporter::importTexture(TextureImportArgs{
.filePath = sourcePath / "import/textures/azeroth_height.png",
});
//AssetImporter::importMesh(MeshImportArgs{
// .filePath = sourcePath / "import/models/after-the-rain-vr-sound/source/Whitechapel.glb",
// .importPath = "Whitechapel",
//});
// AssetImporter::importMesh(MeshImportArgs{521
// .filePath = sourcePath / "import/models/city-suburbs/source/city-suburbs.obj",
// .importPath = "suburbs",
// });
// AssetImporter::importMesh(MeshImportArgs{
// .filePath = sourcePath / "import/models/minecraft-medieval-city.fbx",
// .importPath = "minecraft",
// .filePath = sourcePath / "import/models/ship.fbx",
// .importPath = "ship",
// });
//AssetImporter::importTexture(TextureImportArgs{
// .filePath = sourcePath / "import/textures/azeroth.png",
//});
//AssetImporter::importTexture(TextureImportArgs{
// .filePath = sourcePath / "import/textures/azeroth_height.png",
//});
//AssetImporter::importTexture(TextureImportArgs{
// .filePath = sourcePath / "import/textures/wgen.png",
//});
// AssetImporter::importMesh(MeshImportArgs{
// .filePath = sourcePath / "import/models/after-the-rain-vr-sound/source/Whitechapel.glb",
// .importPath = "Whitechapel",
// });
// AssetImporter::importMesh(MeshImportArgs{521
// .filePath = sourcePath / "import/models/city-suburbs/source/city-suburbs.obj",
// .importPath = "suburbs",
// });
// AssetImporter::importMesh(MeshImportArgs{
// .filePath = sourcePath / "import/models/minecraft-medieval-city.fbx",
// .importPath = "minecraft",
// });
// AssetImporter::importMesh(MeshImportArgs{
// .filePath = sourcePath / "import/models/Volvo/Volvo.fbx",
// .importPath = "Volvo",
// });
AssetImporter::importMesh(MeshImportArgs{
.filePath = sourcePath / "import/models/Volvo/Volvo.fbx",
.importPath = "Volvo",
});
getThreadPool().waitIdle();
vd->commitMeshes();
WindowCreateInfo mainWindowInfo = {
+21 -21
View File
@@ -466,25 +466,25 @@ template <typename T, size_t N> struct StaticArray {
using reference = X&;
using pointer = X*;
IteratorBase(X* x = nullptr) : p(x) {}
reference operator*() const { return *p; }
pointer operator->() const { return p; }
inline bool operator!=(const IteratorBase& other) { return p != other.p; }
inline bool operator==(const IteratorBase& other) { return p == other.p; }
IteratorBase& operator++() {
constexpr IteratorBase(X* x = nullptr) : p(x) {}
constexpr reference operator*() const { return *p; }
constexpr pointer operator->() const { return p; }
constexpr bool operator!=(const IteratorBase& other) { return p != other.p; }
constexpr bool operator==(const IteratorBase& other) { return p == other.p; }
constexpr IteratorBase& operator++() {
p++;
return *this;
}
IteratorBase operator++(int) {
constexpr IteratorBase operator++(int) {
IteratorBase tmp(*this);
++*this;
return tmp;
}
IteratorBase& operator--() {
constexpr IteratorBase& operator--() {
p--;
return *this;
}
IteratorBase operator--(int) {
constexpr IteratorBase operator--(int) {
IteratorBase tmp(*this);
--*this;
return tmp;
@@ -507,18 +507,18 @@ template <typename T, size_t N> struct StaticArray {
using reverse_iterator = std::reverse_iterator<iterator>;
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
StaticArray() {
constexpr StaticArray() {
beginIt = iterator(_data);
endIt = iterator(_data + N);
}
StaticArray(T value) {
constexpr StaticArray(T value) {
for (size_t i = 0; i < N; ++i) {
_data[i] = value;
}
beginIt = iterator(_data);
endIt = iterator(_data + N);
}
StaticArray(std::initializer_list<T> init) {
constexpr StaticArray(std::initializer_list<T> init) {
auto beg = init.begin();
for (size_t i = 0; i < N; ++i) {
_data[i] = *beg;
@@ -527,11 +527,11 @@ template <typename T, size_t N> struct StaticArray {
}
}
}
~StaticArray() {}
constexpr ~StaticArray() {}
inline size_type size() const { return N; }
inline pointer data() { return _data; }
inline const_pointer data() const { return _data; }
constexpr size_type size() const { return N; }
constexpr pointer data() { return _data; }
constexpr const_pointer data() const { return _data; }
template <typename I> constexpr reference operator[](I index) noexcept { return operator[](static_cast<size_t>(index)); }
template <typename I> constexpr const_reference operator[](I index) const noexcept { return operator[](static_cast<size_t>(index)); }
constexpr reference operator[](size_type index) noexcept {
@@ -542,13 +542,13 @@ template <typename T, size_t N> struct StaticArray {
assert(index < N);
return _data[index];
}
iterator begin() { return beginIt; }
iterator end() { return endIt; }
const_iterator begin() const { return beginIt; }
const_iterator end() const { return beginIt; }
constexpr iterator begin() { return beginIt; }
constexpr iterator end() { return endIt; }
constexpr const_iterator begin() const { return beginIt; }
constexpr const_iterator end() const { return beginIt; }
private:
T _data[N];
T _data[N] = {T()};
iterator beginIt;
iterator endIt;
};
+797
View File
@@ -0,0 +1,797 @@
#include "CBT.h"
#include "Graphics/Shader.h"
using namespace Seele;
Array<Vector4> basePoints = {
Vector4(000.0f / 3, 0, 000.0f / 3, 1), Vector4(000.0f / 3, 0, 100.0f / 3, 1), Vector4(000.0f / 3, 0, 200.0f / 3, 1),
Vector4(000.0f / 3, 0, 300.0f / 3, 1), Vector4(100.0f / 3, 0, 000.0f / 3, 1), Vector4(100.0f / 3, 0, 100.0f / 3, 1),
Vector4(100.0f / 3, 0, 200.0f / 3, 1), Vector4(100.0f / 3, 0, 300.0f / 3, 1), Vector4(200.0f / 3, 0, 000.0f / 3, 1),
Vector4(200.0f / 3, 0, 100.0f / 3, 1), Vector4(200.0f / 3, 0, 200.0f / 3, 1), Vector4(200.0f / 3, 0, 300.0f / 3, 1),
Vector4(300.0f / 3, 0, 000.0f / 3, 1), Vector4(300.0f / 3, 0, 100.0f / 3, 1), Vector4(300.0f / 3, 0, 200.0f / 3, 1),
Vector4(300.0f / 3, 0, 300.0f / 3, 1),
};
struct Halfedge {
uint32 vertexID;
uint32 nextID;
uint32 prevID;
uint32 twinID;
};
Array<Halfedge> edges = {
Halfedge{0, 1, 2, 4294967295},
Halfedge{1, 2, 0, 3},
Halfedge{4, 0, 1, 4294967295},
Halfedge{4, 4, 5, 1},
Halfedge{1, 5, 3, 8},
Halfedge{5, 3, 4, 18},
Halfedge{1, 7, 8, 4294967295},
Halfedge{2, 8, 6, 9},
Halfedge{5, 6, 7, 4},
Halfedge{5, 10, 11, 7},
Halfedge{2, 11, 9, 14},
Halfedge{6, 9, 10, 24},
Halfedge{2, 13, 14, 4294967295},
Halfedge{3, 14, 12, 15},
Halfedge{6, 12, 13, 10},
Halfedge{6, 16, 17, 13},
Halfedge{3, 17, 15, 4294967295},
Halfedge{7, 15, 16, 30},
Halfedge{4, 19, 20, 5},
Halfedge{5, 20, 18, 21},
Halfedge{8, 18, 19, 4294967295},
Halfedge{8, 22, 23, 19},
Halfedge{5, 23, 21, 26},
Halfedge{9, 21, 22, 36},
Halfedge{5, 25, 26, 11},
Halfedge{6, 26, 24, 27},
Halfedge{9, 24, 25, 22},
Halfedge{9, 28, 29, 25},
Halfedge{6, 29, 27, 32},
Halfedge{10, 27, 28, 42},
Halfedge{6, 31, 32, 17},
Halfedge{7, 32, 30, 33},
Halfedge{10, 30, 31, 28},
Halfedge{10, 34, 35, 31},
Halfedge{7, 35, 33, 4294967295},
Halfedge{11, 33, 34, 48},
Halfedge{8, 37, 38, 23},
Halfedge{9, 38, 36, 39},
Halfedge{12, 36, 37, 4294967295},
Halfedge{12, 40, 41, 37},
Halfedge{9, 41, 39, 44},
Halfedge{13, 39, 40, 4294967295},
Halfedge{9, 43, 44, 29},
Halfedge{10, 44, 42, 45},
Halfedge{13, 42, 43, 40},
Halfedge{13, 46, 47, 43},
Halfedge{10, 47, 45, 50},
Halfedge{14, 45, 46, 4294967295},
Halfedge{10, 49, 50, 35},
Halfedge{11, 50, 48, 51},
Halfedge{14, 48, 49, 46},
Halfedge{14, 52, 53, 49},
Halfedge{11, 53, 51, 4294967295},
Halfedge{15, 51, 52, 4294967295},
};
uint32_t find_msb_64(uint64_t x) {
uint32_t depth = 0;
while (x > 0u) {
++depth;
x >>= 1uLL;
}
return depth;
}
CPUMesh Seele::generateCPUMesh(uint32 cbtNumElements) {
CPUMesh result;
result.totalNumElements = edges.size() + cbtNumElements;
result.heapIDArray.resize(result.totalNumElements);
result.neighborsArray.resize(result.totalNumElements);
std::memset(result.heapIDArray.data(), 0, result.totalNumElements * sizeof(uint64));
std::memset(result.neighborsArray.data(), 0, result.totalNumElements * sizeof(UVector));
result.minimalDepth = std::min(find_msb_64(edges.size()), 63u) + 1;
const uint64 baseHeapID = 1ull << (result.minimalDepth - 1);
result.basePoints.resize(edges.size() * 3);
UVector neighbours;
for (uint32 halfedgeIdx = 0; halfedgeIdx < (uint32)edges.size(); ++halfedgeIdx) {
uint32 elementID = cbtNumElements + halfedgeIdx;
result.heapIDArray[elementID] = baseHeapID + halfedgeIdx;
Halfedge& halfedge = edges[halfedgeIdx];
neighbours.x = halfedge.prevID != -1 ? cbtNumElements + halfedge.prevID : UINT32_MAX;
neighbours.y = halfedge.nextID != -1 ? cbtNumElements + halfedge.nextID : UINT32_MAX;
neighbours.z = halfedge.twinID != -1 ? cbtNumElements + halfedge.twinID : UINT32_MAX;
result.neighborsArray[elementID] = UVector4(neighbours, 1);
result.basePoints[3 * halfedgeIdx + 2] = basePoints[halfedge.vertexID];
Halfedge& nextHalfedge = edges[halfedge.nextID];
result.basePoints[3 * halfedgeIdx + 0] = basePoints[nextHalfedge.vertexID];
Vector thirdVertex = result.basePoints[3 * halfedgeIdx + 2];
float sumWeight = 1.0f;
uint32 currentIdx = halfedge.nextID;
while (currentIdx != halfedgeIdx) {
Halfedge currentHalfedge = edges[currentIdx];
Vector vp = basePoints[currentHalfedge.vertexID];
thirdVertex += vp;
sumWeight += 1.0f;
currentIdx = currentHalfedge.nextID;
}
result.basePoints[3 * halfedgeIdx + 1] = Vector4(thirdVertex / sumWeight, 1);
}
return result;
}
Matrix3 splittingMatrix(uint32 bitValue) {
float b = float(bitValue);
float c = 1.0f - b;
return glm::transpose(Matrix3({
0.0f,
b,
c,
0.5f,
0.0f,
0.5f,
b,
c,
0.0f,
}));
}
Matrix3 decodeSubdivisionMatrix(uint64 heapID) {
Matrix3 m = Matrix3({1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f});
int32 depth = find_msb_64(heapID) - 1;
for (int32 bitID = depth - 1; bitID >= 0; --bitID) {
m = splittingMatrix((heapID >> bitID) & 1u) * m;
}
return m;
}
void LebMatrixCache::init(Gfx::PGraphics graphics, uint32 depth) {
cacheDepth = depth;
uint32 matrixCount = 2ULL << cacheDepth;
struct PaddedMatrix
{
Matrix3 m;
uint8 pad[12];
};
std::vector<PaddedMatrix> table(matrixCount);
table[0].m = Matrix3({1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f});
for (uint64 heapID = 1ULL; heapID < (2ULL << cacheDepth); ++heapID) {
table[heapID].m = decodeSubdivisionMatrix(heapID);
}
lebMatrixBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
.sourceData =
{
.size = sizeof(PaddedMatrix) * matrixCount,
.data = (uint8*)table.data(),
},
.name = "LebMatrixCache",
});
lebMatrixBuffer->pipelineBarrier(Gfx::SE_ACCESS_TRANSFER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT,
Gfx::SE_ACCESS_SHADER_READ_BIT | Gfx::SE_ACCESS_SHADER_WRITE_BIT,
Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
}
void LebMatrixCache::release() {}
void MeshUpdater::init(Gfx::PGraphics gfx, Gfx::PDescriptorLayout viewParamsLayout) {
graphics = gfx;
layout = graphics->createDescriptorLayout("pParams");
layout->addDescriptorBinding(Gfx::DescriptorBinding{0, Gfx::SE_DESCRIPTOR_TYPE_UNIFORM_BUFFER});
layout->addDescriptorBinding(Gfx::DescriptorBinding{1, Gfx::SE_DESCRIPTOR_TYPE_UNIFORM_BUFFER});
layout->addDescriptorBinding(Gfx::DescriptorBinding{2, Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER});
layout->addDescriptorBinding(Gfx::DescriptorBinding{3, Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER});
layout->addDescriptorBinding(Gfx::DescriptorBinding{4, Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER});
layout->addDescriptorBinding(Gfx::DescriptorBinding{5, Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER});
layout->addDescriptorBinding(Gfx::DescriptorBinding{6, Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER});
layout->addDescriptorBinding(Gfx::DescriptorBinding{7, Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER});
layout->addDescriptorBinding(Gfx::DescriptorBinding{8, Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER});
layout->addDescriptorBinding(Gfx::DescriptorBinding{9, Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER});
layout->addDescriptorBinding(Gfx::DescriptorBinding{10, Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER});
layout->addDescriptorBinding(Gfx::DescriptorBinding{11, Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER});
layout->addDescriptorBinding(Gfx::DescriptorBinding{12, Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER});
layout->addDescriptorBinding(Gfx::DescriptorBinding{13, Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER});
layout->addDescriptorBinding(Gfx::DescriptorBinding{14, Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER});
layout->addDescriptorBinding(Gfx::DescriptorBinding{15, Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER});
layout->addDescriptorBinding(Gfx::DescriptorBinding{16, Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER});
layout->addDescriptorBinding(Gfx::DescriptorBinding{17, Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER});
layout->addDescriptorBinding(Gfx::DescriptorBinding{18, Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER});
layout->addDescriptorBinding(Gfx::DescriptorBinding{19, Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER});
layout->addDescriptorBinding(Gfx::DescriptorBinding{20, Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER});
layout->addDescriptorBinding(Gfx::DescriptorBinding{21, Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER});
layout->addDescriptorBinding(Gfx::DescriptorBinding{22, Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER});
layout->create();
pipelineLayout = graphics->createPipelineLayout("ComputeLayout");
pipelineLayout->addDescriptorLayout(viewParamsLayout);
pipelineLayout->addDescriptorLayout(layout);
indirectBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
.sourceData =
{
.size = sizeof(uint32) * 9,
},
.usage = Gfx::SE_BUFFER_USAGE_INDIRECT_BUFFER_BIT,
.name = "IndirectBuffer",
});
memoryBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
.sourceData =
{
.size = sizeof(int32) * 2,
},
.name = "MemoryBuffer",
});
validationBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
.sourceData =
{
.size = sizeof(int32) * 2,
},
.name = "ValidationBuffer",
});
validationBufferRB = graphics->createShaderBuffer(ShaderBufferCreateInfo{
.sourceData =
{
.size = sizeof(int32) * 2,
},
.name = "ValidationBufferRB",
});
occupancyBufferRB = graphics->createShaderBuffer(ShaderBufferCreateInfo{
.sourceData =
{
.size = sizeof(uint32),
},
.name = "OccupancyBuffer",
});
graphics->beginShaderCompilation(ShaderCompilationInfo{
.name = "CBTCompute",
.modules = {"CBTCompute"},
.entryPoints =
{
{"reset", "CBTCompute"},
{"classify", "CBTCompute"},
{"split", "CBTCompute"},
{"prepareIndirect", "CBTCompute"},
{"allocate", "CBTCompute"},
{"bisect", "CBTCompute"},
{"propagateBisect", "CBTCompute"},
{"prepareSimplify", "CBTCompute"},
{"simplify", "CBTCompute"},
{"propagateSimplify", "CBTCompute"},
{"reducePrePass", "CBTCompute"},
{"reduceFirstPass", "CBTCompute"},
{"reduceSecondPass", "CBTCompute"},
{"bisectorIndexation", "CBTCompute"},
{"prepareBisectorIndirect", "CBTCompute"},
{"validate", "CBTCompute"},
{"clearLeb", "CBTCompute"},
{"evaluateLeb", "CBTCompute"},
},
.rootSignature = pipelineLayout,
});
pipelineLayout->create();
resetCS = graphics->createComputeShader({0});
reset = graphics->createComputePipeline(Gfx::ComputePipelineCreateInfo{
.computeShader = resetCS,
.pipelineLayout = pipelineLayout,
});
classifyCS = graphics->createComputeShader({1});
classify = graphics->createComputePipeline(Gfx::ComputePipelineCreateInfo{
.computeShader = classifyCS,
.pipelineLayout = pipelineLayout,
});
splitCS = graphics->createComputeShader({2});
split = graphics->createComputePipeline(Gfx::ComputePipelineCreateInfo{
.computeShader = splitCS,
.pipelineLayout = pipelineLayout,
});
prepareIndirectCS = graphics->createComputeShader({3});
prepareIndirect = graphics->createComputePipeline(Gfx::ComputePipelineCreateInfo{
.computeShader = prepareIndirectCS,
.pipelineLayout = pipelineLayout,
});
allocateCS = graphics->createComputeShader({4});
allocate = graphics->createComputePipeline(Gfx::ComputePipelineCreateInfo{
.computeShader = allocateCS,
.pipelineLayout = pipelineLayout,
});
bisectCS = graphics->createComputeShader({5});
bisect = graphics->createComputePipeline(Gfx::ComputePipelineCreateInfo{
.computeShader = bisectCS,
.pipelineLayout = pipelineLayout,
});
propagateBisectCS = graphics->createComputeShader({6});
propagateBisect = graphics->createComputePipeline(Gfx::ComputePipelineCreateInfo{
.computeShader = propagateBisectCS,
.pipelineLayout = pipelineLayout,
});
prepareSimplifyCS = graphics->createComputeShader({7});
prepareSimplify = graphics->createComputePipeline(Gfx::ComputePipelineCreateInfo{
.computeShader = prepareSimplifyCS,
.pipelineLayout = pipelineLayout,
});
simplifyCS = graphics->createComputeShader({8});
simplify = graphics->createComputePipeline(Gfx::ComputePipelineCreateInfo{
.computeShader = simplifyCS,
.pipelineLayout = pipelineLayout,
});
propagateSimplifyCS = graphics->createComputeShader({9});
propagateSimplify = graphics->createComputePipeline(Gfx::ComputePipelineCreateInfo{
.computeShader = propagateSimplifyCS,
.pipelineLayout = pipelineLayout,
});
reducePrePassCS = graphics->createComputeShader({10});
reducePrePass = graphics->createComputePipeline(Gfx::ComputePipelineCreateInfo{
.computeShader = reducePrePassCS,
.pipelineLayout = pipelineLayout,
});
reduceFirstPassCS = graphics->createComputeShader({11});
reduceFirstPass = graphics->createComputePipeline(Gfx::ComputePipelineCreateInfo{
.computeShader = reduceFirstPassCS,
.pipelineLayout = pipelineLayout,
});
reduceSecondPassCS = graphics->createComputeShader({12});
reduceSecondPass = graphics->createComputePipeline(Gfx::ComputePipelineCreateInfo{
.computeShader = reduceSecondPassCS,
.pipelineLayout = pipelineLayout,
});
bisectorIndexationCS = graphics->createComputeShader({13});
bisectorIndexation = graphics->createComputePipeline(Gfx::ComputePipelineCreateInfo{
.computeShader = bisectorIndexationCS,
.pipelineLayout = pipelineLayout,
});
prepareBisectorIndirectCS = graphics->createComputeShader({14});
prepareBisectorIndirect = graphics->createComputePipeline(Gfx::ComputePipelineCreateInfo{
.computeShader = prepareBisectorIndirectCS,
.pipelineLayout = pipelineLayout,
});
validateCS = graphics->createComputeShader({15});
validate = graphics->createComputePipeline(Gfx::ComputePipelineCreateInfo{
.computeShader = validateCS,
.pipelineLayout = pipelineLayout,
});
lebClearCS = graphics->createComputeShader({16});
lebClear = graphics->createComputePipeline(Gfx::ComputePipelineCreateInfo{
.computeShader = lebClearCS,
.pipelineLayout = pipelineLayout,
});
lebEvaluateCS = graphics->createComputeShader({17});
lebEvaluate = graphics->createComputePipeline(Gfx::ComputePipelineCreateInfo{
.computeShader = lebEvaluateCS,
.pipelineLayout = pipelineLayout,
});
}
void MeshUpdater::release() {}
void MeshUpdater::evaluateLeb(const BaseMesh& baseMesh, CBTMesh& mesh, Gfx::PDescriptorSet viewParamsSet,
Gfx::PUniformBuffer geometryBuffer, Gfx::PUniformBuffer updateBuffer, Gfx::PShaderBuffer lebMatrixCache,
bool clear, bool complete) {
if (clear) {
Gfx::PDescriptorSet set = layout->allocateDescriptorSet();
set->updateBuffer(GEOMETRY_CB, 0, geometryBuffer);
set->updateBuffer(LEB_POSITION_BUFFER, 0, mesh.currentVertexBuffer);
set->writeChanges();
Gfx::OComputeCommand clearCmd = graphics->createComputeCommand("Clear");
clearCmd->bindPipeline(lebClear);
clearCmd->bindDescriptor(set);
clearCmd->dispatch((mesh.totalNumElements * 3 + WORKGROUP_SIZE - 1) / WORKGROUP_SIZE, 1, 1);
mesh.currentVertexBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
}
Gfx::PDescriptorSet set = layout->allocateDescriptorSet();
set->updateBuffer(GEOMETRY_CB, 0, geometryBuffer);
set->updateBuffer(UPDATE_CB, 0, updateBuffer);
set->updateBuffer(CURRENT_VERTEX_BUFFER, 0, baseMesh.vertexBuffer);
set->updateBuffer(HEAP_ID_BUFFER, 0, mesh.heapIDBuffer);
set->updateBuffer(INDEXED_BISECTOR_BUFFER, 0, complete ? mesh.indexedBisectorBuffer : mesh.modifiedIndexedBisectorBuffer);
set->updateBuffer(INDIRECT_DRAW_BUFFER, 0, mesh.indirectDrawBuffer);
set->updateBuffer(LEB_MATRIX_CACHE, 0, lebMatrixCache);
set->updateBuffer(LEB_POSITION_BUFFER, 0, mesh.lebVertexBuffer);
set->writeChanges();
Gfx::OComputeCommand evalCmd = graphics->createComputeCommand("EvalLEB");
evalCmd->bindPipeline(lebEvaluate);
evalCmd->bindDescriptor({set, viewParamsSet});
evalCmd->dispatchIndirect(mesh.indirectDispatchBuffer, complete ? 0 : sizeof(uint32) * 6);
graphics->executeCommands(std::move(evalCmd));
mesh.currentVertexBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
}
void MeshUpdater::update(CBTMesh& mesh, Gfx::PDescriptorSet viewParamsSet, Gfx::PUniformBuffer geometryCB, Gfx::PUniformBuffer updateCB) {
uint32 nextNeighborsBufferIdx = (mesh.currentNeighborsBufferIdx + 1) % 2;
Gfx::PShaderBuffer currentNeighborsBuffer = mesh.neighborsBuffers[mesh.currentNeighborsBufferIdx];
Gfx::PShaderBuffer nextNeighborsBuffer = mesh.neighborsBuffers[nextNeighborsBufferIdx];
resetBuffers(mesh);
// classify
{
Gfx::PDescriptorSet set = layout->allocateDescriptorSet();
set->updateBuffer(GEOMETRY_CB, 0, geometryCB);
set->updateBuffer(UPDATE_CB, 0, updateCB);
set->updateBuffer(CURRENT_VERTEX_BUFFER, 0, mesh.currentVertexBuffer);
set->updateBuffer(INDEXED_BISECTOR_BUFFER, 0, mesh.indexedBisectorBuffer);
set->updateBuffer(INDIRECT_DRAW_BUFFER, 0, mesh.indirectDrawBuffer);
set->updateBuffer(HEAP_ID_BUFFER, 0, mesh.heapIDBuffer);
set->updateBuffer(BISECTOR_DATA_BUFFER, 0, mesh.updateBuffer);
set->updateBuffer(CLASSIFICATION_BUFFER, 0, mesh.classificationBuffer);
set->writeChanges();
Gfx::OComputeCommand classifyCmd = graphics->createComputeCommand("Classify");
classifyCmd->bindPipeline(classify);
classifyCmd->bindDescriptor({viewParamsSet, set});
classifyCmd->dispatchIndirect(mesh.indirectDispatchBuffer, 0);
graphics->executeCommands(std::move(classifyCmd));
mesh.updateBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
}
// prepare indirect pass
{
Gfx::PDescriptorSet set = layout->allocateDescriptorSet();
set->updateBuffer(ALLOCATE_BUFFER, 0, mesh.classificationBuffer);
set->updateBuffer(INDIRECT_DISPATCH_BUFFER, 0, indirectBuffer);
set->writeChanges();
Gfx::OComputeCommand prepareIndirectCmd = graphics->createComputeCommand("PrepareIndirect");
prepareIndirectCmd->bindPipeline(prepareIndirect);
prepareIndirectCmd->bindDescriptor(set);
prepareIndirectCmd->dispatch(2, 1, 1);
graphics->executeCommands(std::move(prepareIndirectCmd));
indirectBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
}
// split pass
{
Gfx::PDescriptorSet set = layout->allocateDescriptorSet();
set->updateBuffer(GEOMETRY_CB, 0, geometryCB);
set->updateBuffer(UPDATE_CB, 0, updateCB);
set->updateBuffer(CLASSIFICATION_BUFFER, 0, mesh.classificationBuffer);
set->updateBuffer(HEAP_ID_BUFFER, 0, mesh.heapIDBuffer);
set->updateBuffer(BISECTOR_DATA_BUFFER, 0, mesh.updateBuffer);
set->updateBuffer(NEIGHBOURS_BUFFER, 0, currentNeighborsBuffer);
set->updateBuffer(MEMORY_BUFFER, 0, memoryBuffer);
set->updateBuffer(ALLOCATE_BUFFER, 0, mesh.allocateBuffer);
set->writeChanges();
Gfx::OComputeCommand splitCmd = graphics->createComputeCommand("Split");
splitCmd->bindPipeline(split);
splitCmd->bindDescriptor({viewParamsSet, set});
splitCmd->dispatchIndirect(indirectBuffer, 0);
graphics->executeCommands(std::move(splitCmd));
mesh.updateBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
}
// prepare indirect pass
{
Gfx::PDescriptorSet set = layout->allocateDescriptorSet();
set->updateBuffer(ALLOCATE_BUFFER, 0, mesh.allocateBuffer);
set->updateBuffer(INDIRECT_DISPATCH_BUFFER, 0, indirectBuffer);
set->writeChanges();
Gfx::OComputeCommand prepareIndirectCmd = graphics->createComputeCommand("PrepareIndirect");
prepareIndirectCmd->bindPipeline(prepareIndirect);
prepareIndirectCmd->bindDescriptor(set);
prepareIndirectCmd->dispatch(1, 1, 1);
graphics->executeCommands(std::move(prepareIndirectCmd));
indirectBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
}
// Allocate Pass
{
Gfx::PDescriptorSet set = layout->allocateDescriptorSet();
set->updateBuffer(GEOMETRY_CB, 0, geometryCB);
set->updateBuffer(UPDATE_CB, 0, updateCB);
set->updateBuffer(CBT_BUFFER0, 0, mesh.gpuCBT.bufferArray[0]);
set->updateBuffer(CBT_BUFFER1, 0, mesh.gpuCBT.bufferArray[1]);
set->updateBuffer(ALLOCATE_BUFFER, 0, mesh.allocateBuffer);
set->updateBuffer(BISECTOR_DATA_BUFFER, 0, mesh.updateBuffer);
set->updateBuffer(MEMORY_BUFFER, 0, memoryBuffer);
set->writeChanges();
Gfx::OComputeCommand allocateCmd = graphics->createComputeCommand("Allocate");
allocateCmd->bindPipeline(allocate);
allocateCmd->bindDescriptor({viewParamsSet, set});
allocateCmd->dispatchIndirect(indirectBuffer, 0);
graphics->executeCommands(std::move(allocateCmd));
mesh.updateBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
}
// copy
currentNeighborsBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
Gfx::SE_ACCESS_TRANSFER_READ_BIT, Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT);
graphics->copyBuffer(currentNeighborsBuffer, nextNeighborsBuffer);
nextNeighborsBuffer->pipelineBarrier(Gfx::SE_ACCESS_TRANSFER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT,
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
// bisect
{
Gfx::PDescriptorSet set = layout->allocateDescriptorSet();
set->updateBuffer(GEOMETRY_CB, 0, geometryCB);
set->updateBuffer(UPDATE_CB, 0, updateCB);
set->updateBuffer(CBT_BUFFER0, 0, mesh.gpuCBT.bufferArray[0]);
set->updateBuffer(CBT_BUFFER1, 0, mesh.gpuCBT.bufferArray[1]);
set->updateBuffer(ALLOCATE_BUFFER, 0, mesh.allocateBuffer);
set->updateBuffer(HEAP_ID_BUFFER, 0, mesh.heapIDBuffer);
set->updateBuffer(BISECTOR_DATA_BUFFER, 0, mesh.updateBuffer);
set->updateBuffer(NEIGHBOURS_BUFFER, 0, currentNeighborsBuffer);
set->updateBuffer(NEIGHBOURS_OUTPUT_BUFFER, 0, nextNeighborsBuffer);
set->updateBuffer(PROPAGATE_BUFFER, 0, mesh.propagateBuffer);
set->writeChanges();
Gfx::OComputeCommand bisectCmd = graphics->createComputeCommand("Bisect");
bisectCmd->bindPipeline(bisect);
bisectCmd->bindDescriptor({viewParamsSet, set});
bisectCmd->dispatchIndirect(indirectBuffer, 0);
graphics->executeCommands(std::move(bisectCmd));
nextNeighborsBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
}
// Prepare indirect pass
{
Gfx::PDescriptorSet set = layout->allocateDescriptorSet();
set->updateBuffer(ALLOCATE_BUFFER, 0, mesh.propagateBuffer);
set->updateBuffer(INDIRECT_DISPATCH_BUFFER, 0, indirectBuffer);
set->writeChanges();
Gfx::OComputeCommand prepareIndirectCmd = graphics->createComputeCommand("PrepareIndirectPropagateBisect");
prepareIndirectCmd->bindPipeline(prepareIndirect);
prepareIndirectCmd->bindDescriptor(set);
prepareIndirectCmd->dispatch(1, 1, 1);
graphics->executeCommands(std::move(prepareIndirectCmd));
indirectBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
}
// propagate split pass
{
Gfx::PDescriptorSet set = layout->allocateDescriptorSet();
set->updateBuffer(GEOMETRY_CB, 0, geometryCB);
set->updateBuffer(UPDATE_CB, 0, updateCB);
set->updateBuffer(PROPAGATE_BUFFER, 0, mesh.propagateBuffer);
set->updateBuffer(BISECTOR_DATA_BUFFER, 0, mesh.updateBuffer);
set->updateBuffer(NEIGHBOURS_BUFFER, 0, nextNeighborsBuffer);
set->writeChanges();
Gfx::OComputeCommand propagateBisectCmd = graphics->createComputeCommand("PropagateBisect");
propagateBisectCmd->bindPipeline(propagateBisect);
propagateBisectCmd->bindDescriptor({viewParamsSet, set});
propagateBisectCmd->dispatchIndirect(indirectBuffer, 0);
graphics->executeCommands(std::move(propagateBisectCmd));
mesh.updateBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
}
// prepare simplify
{
Gfx::PDescriptorSet set = layout->allocateDescriptorSet();
set->updateBuffer(GEOMETRY_CB, 0, geometryCB);
set->updateBuffer(UPDATE_CB, 0, updateCB);
set->updateBuffer(CLASSIFICATION_BUFFER, 0, mesh.classificationBuffer);
set->updateBuffer(HEAP_ID_BUFFER, 0, mesh.heapIDBuffer);
set->updateBuffer(BISECTOR_DATA_BUFFER, 0, mesh.updateBuffer);
set->updateBuffer(NEIGHBOURS_BUFFER, 0, nextNeighborsBuffer);
set->updateBuffer(SIMPLIFICATION_BUFFER, 0, mesh.simplificationBuffer);
set->writeChanges();
Gfx::OComputeCommand prepareSimplifyCmd = graphics->createComputeCommand("PrepareSimplify");
prepareSimplifyCmd->bindPipeline(prepareSimplify);
prepareSimplifyCmd->bindDescriptor({viewParamsSet, set});
prepareSimplifyCmd->dispatchIndirect(indirectBuffer, 0);
graphics->executeCommands(std::move(prepareSimplifyCmd));
mesh.simplificationBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
}
// Prepare Indirect Simplify
{
Gfx::PDescriptorSet set = layout->allocateDescriptorSet();
set->updateBuffer(ALLOCATE_BUFFER, 0, mesh.simplificationBuffer);
set->updateBuffer(INDIRECT_DISPATCH_BUFFER, 0, indirectBuffer);
set->writeChanges();
Gfx::OComputeCommand prepareIndirectCmd = graphics->createComputeCommand("PrepareIndirectSimplify");
prepareIndirectCmd->bindPipeline(prepareIndirect);
prepareIndirectCmd->bindDescriptor(set);
prepareIndirectCmd->dispatch(1, 1, 1);
graphics->executeCommands(std::move(prepareIndirectCmd));
indirectBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
}
// Simplify Pass
{
Gfx::PDescriptorSet set = layout->allocateDescriptorSet();
set->updateBuffer(GEOMETRY_CB, 0, geometryCB);
set->updateBuffer(UPDATE_CB, 0, updateCB);
set->updateBuffer(SIMPLIFICATION_BUFFER, 0, mesh.simplificationBuffer);
set->updateBuffer(BISECTOR_DATA_BUFFER, 0, mesh.updateBuffer);
set->updateBuffer(NEIGHBOURS_BUFFER, 0, nextNeighborsBuffer);
set->updateBuffer(HEAP_ID_BUFFER, 0, mesh.heapIDBuffer);
set->updateBuffer(CBT_BUFFER0, 0, mesh.gpuCBT.bufferArray[0]);
set->updateBuffer(CBT_BUFFER1, 0, mesh.gpuCBT.bufferArray[1]);
set->updateBuffer(PROPAGATE_BUFFER, 0, mesh.propagateBuffer);
set->writeChanges();
Gfx::OComputeCommand simplifyCmd = graphics->createComputeCommand("simplify");
simplifyCmd->bindPipeline(simplify);
simplifyCmd->bindDescriptor({viewParamsSet, set});
simplifyCmd->dispatchIndirect(indirectBuffer, 0);
graphics->executeCommands(std::move(simplifyCmd));
nextNeighborsBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
}
// Prepare Indirect Propagate Simplify
{
Gfx::PDescriptorSet set = layout->allocateDescriptorSet();
set->updateBuffer(ALLOCATE_BUFFER, 0, mesh.propagateBuffer);
set->updateBuffer(INDIRECT_DISPATCH_BUFFER, 0, indirectBuffer);
set->writeChanges();
Gfx::OComputeCommand prepareIndirectCmd = graphics->createComputeCommand("PrepareIndirectPropagateSimplify");
prepareIndirectCmd->bindPipeline(prepareIndirect);
prepareIndirectCmd->bindDescriptor({viewParamsSet, set});
prepareIndirectCmd->dispatch(2, 1, 1);
graphics->executeCommands(std::move(prepareIndirectCmd));
indirectBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
}
// Propagate Simplify Pass
{
Gfx::PDescriptorSet set = layout->allocateDescriptorSet();
set->updateBuffer(GEOMETRY_CB, 0, geometryCB);
set->updateBuffer(UPDATE_CB, 0, updateCB);
set->updateBuffer(SIMPLIFICATION_BUFFER, 0, mesh.simplificationBuffer);
set->updateBuffer(BISECTOR_DATA_BUFFER, 0, mesh.updateBuffer);
set->updateBuffer(NEIGHBOURS_BUFFER, 0, nextNeighborsBuffer);
set->updateBuffer(HEAP_ID_BUFFER, 0, mesh.heapIDBuffer);
set->updateBuffer(CBT_BUFFER0, 0, mesh.gpuCBT.bufferArray[0]);
set->updateBuffer(CBT_BUFFER1, 0, mesh.gpuCBT.bufferArray[1]);
set->updateBuffer(PROPAGATE_BUFFER, 0, mesh.propagateBuffer);
set->writeChanges();
Gfx::OComputeCommand simplifyCmd = graphics->createComputeCommand("simplify");
simplifyCmd->bindPipeline(simplify);
simplifyCmd->bindDescriptor({viewParamsSet, set});
simplifyCmd->dispatchIndirect(indirectBuffer, 0);
graphics->executeCommands(std::move(simplifyCmd));
nextNeighborsBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
}
// Update Tree
{
Gfx::PDescriptorSet set = layout->allocateDescriptorSet();
set->updateBuffer(CBT_BUFFER0, 0, mesh.gpuCBT.bufferArray[0]);
set->updateBuffer(CBT_BUFFER1, 0, mesh.gpuCBT.bufferArray[1]);
set->writeChanges();
Gfx::OComputeCommand reducePrePassCmd = graphics->createComputeCommand("ReducePrepass");
reducePrePassCmd->bindPipeline(reducePrePass);
reducePrePassCmd->bindDescriptor(set);
reducePrePassCmd->dispatch(mesh.gpuCBT.lastLevelSize / (4 * WORKGROUP_SIZE), 1, 1);
graphics->executeCommands(std::move(reducePrePassCmd));
mesh.gpuCBT.bufferArray[0]->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
Gfx::OComputeCommand reduceFirstPassCmd = graphics->createComputeCommand("ReduceFirstPass");
reduceFirstPassCmd->bindPipeline(reduceFirstPass);
reduceFirstPassCmd->bindDescriptor(set);
reduceFirstPassCmd->dispatch(8, 1, 1);
graphics->executeCommands(std::move(reduceFirstPassCmd));
mesh.gpuCBT.bufferArray[0]->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
Gfx::OComputeCommand reduceSecondPassCmd = graphics->createComputeCommand("ReduceSecondPass");
reduceSecondPassCmd->bindPipeline(reduceSecondPass);
reduceSecondPassCmd->bindDescriptor(set);
reduceSecondPassCmd->dispatch(1, 1, 1);
graphics->executeCommands(std::move(reduceSecondPassCmd));
mesh.gpuCBT.bufferArray[0]->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
}
mesh.currentNeighborsBufferIdx = nextNeighborsBufferIdx;
prepareIndirection(mesh, geometryCB);
}
void MeshUpdater::validation(const CBTMesh& mesh, Gfx::PUniformBuffer geometryCB) {
uint32 numGroups = (mesh.totalNumElements + WORKGROUP_SIZE - 1) / WORKGROUP_SIZE;
Gfx::PDescriptorSet set = layout->allocateDescriptorSet();
set->updateBuffer(GEOMETRY_CB, 0, geometryCB);
set->updateBuffer(HEAP_ID_BUFFER, 0, mesh.heapIDBuffer);
set->updateBuffer(BISECTOR_DATA_BUFFER, 0, mesh.updateBuffer);
set->updateBuffer(NEIGHBOURS_BUFFER, 0, mesh.neighborsBuffers[mesh.currentNeighborsBufferIdx]);
set->updateBuffer(VALIDATION_BUFFER, 0, validationBuffer);
set->writeChanges();
Gfx::OComputeCommand validateCmd = graphics->createComputeCommand("Validate");
validateCmd->bindPipeline(validate);
validateCmd->bindDescriptor(set);
validateCmd->dispatch(numGroups, 1, 1);
graphics->executeCommands(std::move(validateCmd));
validationBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
Gfx::SE_ACCESS_TRANSFER_READ_BIT, Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT);
graphics->copyBuffer(validationBuffer, validationBufferRB);
}
void MeshUpdater::resetBuffers(const CBTMesh& mesh) {
Gfx::PDescriptorSet set = layout->allocateDescriptorSet();
set->updateBuffer(CBT_BUFFER0, 0, mesh.gpuCBT.bufferArray[0]);
set->updateBuffer(CBT_BUFFER1, 0, mesh.gpuCBT.bufferArray[1]);
set->updateBuffer(MEMORY_BUFFER, 0, memoryBuffer);
set->updateBuffer(CLASSIFICATION_BUFFER, 0, mesh.classificationBuffer);
set->updateBuffer(ALLOCATE_BUFFER, 0, mesh.allocateBuffer);
set->updateBuffer(INDIRECT_DRAW_BUFFER, 0, mesh.indirectDrawBuffer);
set->updateBuffer(SIMPLIFICATION_BUFFER, 0, mesh.simplificationBuffer);
set->updateBuffer(PROPAGATE_BUFFER, 0, mesh.propagateBuffer);
set->writeChanges();
Gfx::OComputeCommand resetCmd = graphics->createComputeCommand("Reset");
resetCmd->bindPipeline(reset);
resetCmd->bindDescriptor(set);
resetCmd->dispatch(1, 1, 1);
graphics->executeCommands(std::move(resetCmd));
memoryBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
}
void MeshUpdater::prepareIndirection(CBTMesh& mesh, Gfx::PUniformBuffer geometryCB) {
uint32 numGroups = (mesh.totalNumElements + WORKGROUP_SIZE - 1) / WORKGROUP_SIZE;
// Bitsector indexation
{
Gfx::PDescriptorSet set = layout->allocateDescriptorSet();
set->updateBuffer(GEOMETRY_CB, 0, geometryCB);
set->updateBuffer(HEAP_ID_BUFFER, 0, mesh.heapIDBuffer);
set->updateBuffer(INDIRECT_DRAW_BUFFER, 0, mesh.indirectDrawBuffer);
set->updateBuffer(BISECTOR_INDICES, 0, mesh.indexedBisectorBuffer);
set->updateBuffer(BISECTOR_DATA_BUFFER, 0, mesh.updateBuffer);
set->updateBuffer(NEIGHBOURS_BUFFER, 0, mesh.neighborsBuffers[mesh.currentNeighborsBufferIdx]);
set->updateBuffer(VISIBLE_BISECTOR_INDICES, 0, mesh.visibleIndexedBisectorBuffer);
set->updateBuffer(MODIFIED_BISECTOR_INDICES, 0, mesh.modifiedIndexedBisectorBuffer);
set->writeChanges();
Gfx::OComputeCommand bisectorIndexationCmd = graphics->createComputeCommand("BisectorIndexation");
bisectorIndexationCmd->bindPipeline(bisectorIndexation);
bisectorIndexationCmd->bindDescriptor(set);
bisectorIndexationCmd->dispatch(numGroups, 1, 1);
graphics->executeCommands(std::move(bisectorIndexationCmd));
}
mesh.indirectDrawBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
// Prepare bisector indirect dispatch
{
Gfx::PDescriptorSet set = layout->allocateDescriptorSet();
set->updateBuffer(INDIRECT_DRAW_BUFFER, 0, mesh.indirectDrawBuffer);
set->updateBuffer(INDIRECT_DISPATCH_BUFFER, 0, mesh.indirectDispatchBuffer);
set->writeChanges();
Gfx::OComputeCommand prepareBisectorIndirectCmd = graphics->createComputeCommand("PrepareBisectorIndirect");
prepareBisectorIndirectCmd->bindPipeline(prepareBisectorIndirect);
prepareBisectorIndirectCmd->bindDescriptor(set);
prepareBisectorIndirectCmd->dispatch(1, 1, 1);
graphics->executeCommands(std::move(prepareBisectorIndirectCmd));
mesh.indirectDispatchBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
}
}
bool MeshUpdater::checkIfValid() { return true; }
void MeshUpdater::queryOccupancy(const CBTMesh& mesh) {}
uint32 MeshUpdater::getOccupancy() { return 0; }
+505
View File
@@ -0,0 +1,505 @@
#pragma once
#include "Containers/Array.h"
#include "Graphics/RenderPass/RenderPass.h"
#include "MinimalEngine.h"
#include <bit>
namespace Seele {
constexpr auto GEOMETRY_CB = 0;
constexpr auto UPDATE_CB = 1;
constexpr auto CURRENT_VERTEX_BUFFER = 2;
constexpr auto INDEXED_BISECTOR_BUFFER = 3;
constexpr auto INDIRECT_DRAW_BUFFER = 4;
constexpr auto HEAP_ID_BUFFER = 5;
constexpr auto BISECTOR_DATA_BUFFER = 6;
constexpr auto CLASSIFICATION_BUFFER = 7;
constexpr auto ALLOCATE_BUFFER = 8;
constexpr auto INDIRECT_DISPATCH_BUFFER = 9;
constexpr auto NEIGHBOURS_BUFFER = 10;
constexpr auto NEIGHBOURS_OUTPUT_BUFFER = 11;
constexpr auto MEMORY_BUFFER = 12;
constexpr auto CBT_BUFFER0 = 13;
constexpr auto CBT_BUFFER1 = 14;
constexpr auto PROPAGATE_BUFFER = 15;
constexpr auto SIMPLIFICATION_BUFFER = 16;
constexpr auto VALIDATION_BUFFER = 17;
constexpr auto BISECTOR_INDICES = 18;
constexpr auto VISIBLE_BISECTOR_INDICES = 19;
constexpr auto MODIFIED_BISECTOR_INDICES = 20;
constexpr auto LEB_POSITION_BUFFER = 21;
constexpr auto LEB_MATRIX_CACHE = 22;
constexpr uint64 WORKGROUP_SIZE = 64;
template <size_t Power> class CBT {
private:
struct OCBTTree {
uint64 numElements = 0;
uint64 treeSizeBits = 0;
uint64 numSlots = 0;
uint64 bitFieldNumSlots = 0;
uint64 lastLevelSize = 0;
uint64 lastLevel = 0;
uint64 firstVirtualLevel = 0;
uint64 leafLevel = 0;
StaticArray<uint32, Power> depthOffset;
StaticArray<uint64, Power> bitMask;
StaticArray<uint32, Power> bitCount;
};
OCBTTree tree;
constexpr static OCBTTree generateVirtualLevel(OCBTTree tree, uint64 index, uint64 bits) {
tree.depthOffset[index] = 0;
tree.bitCount[index] = bits;
uint64 bitmask = 0;
for (uint32 i = 0; i < bits; ++i) {
bitmask |= 1ull << i;
}
tree.bitMask[index] = bitmask;
if (bits == 1) {
tree.numSlots = tree.treeSizeBits / 32;
tree.bitFieldNumSlots = tree.numElements / 64;
return tree;
}
return generateVirtualLevel(tree, index++, bits / 2);
}
constexpr static OCBTTree generateLevel(OCBTTree tree, uint64 remaining, uint64 index, uint64 levelElements, uint64 levelDimensions) {
if (remaining == 7) {
tree.depthOffset[index] = tree.treeSizeBits;
tree.bitMask[index] = (1ull << 8) - 1;
tree.bitCount[index] = 8;
tree.treeSizeBits += levelDimensions * 8;
tree.lastLevelSize = levelDimensions;
tree.firstVirtualLevel = std::bit_width(levelDimensions);
tree.lastLevel = tree.firstVirtualLevel - 1;
return generateVirtualLevel(tree, index++, 64);
}
uint32 levelBits;
if (levelDimensions < 128) {
levelBits = 32;
} else {
levelBits = 16;
}
tree.depthOffset[index] = tree.treeSizeBits;
tree.bitMask[index] = (1ull << levelBits) - 1;
tree.bitCount[index] = levelBits;
tree.treeSizeBits += levelDimensions * levelBits;
return generateLevel(tree, --remaining, index++, levelElements / 2, levelDimensions * 2);
}
constexpr static OCBTTree createTree(uint64 power) {
uint64 numElements = (1ull << (power - 1));
return generateLevel(
CBT::OCBTTree{
.numElements = numElements,
.leafLevel = power - 1,
},
power - 1, 0, numElements, 1);
}
public:
constexpr CBT() : tree(createTree(Power)) {
rawMemory = new uint32[tree.numSlots + tree.numElements / 32];
packedHeap = rawMemory;
bitfield = (uint64*)(rawMemory + tree.numSlots);
clear();
}
~CBT() {}
uint32 numElements() { return tree.numElements; }
uint32 lastLevelSize() { return tree.lastLevelSize; }
uint32 maxDepth() { return Power; }
uint32 numInternalBuffers() { return 2; }
char* rawBuffer(uint32 bufferIdx = 0) { return bufferIdx == 0 ? (char*)packedHeap : (char*)bitfield; }
const char* rawBuffer(uint32 bufferIdx = 0) const { return bufferIdx == 0 ? (const char*)packedHeap : (const char*)bitfield; }
uint32 bufferSize(uint32 bufferIdx = 0) const { return bufferIdx == 0 ? treeMemoryFootprint() : bitFieldMemoryFootprint(); }
uint32 elementSize(uint32 bufferIdx) const { return bufferIdx == 0 ? sizeof(uint32) : sizeof(uint64); }
uint32 memoryFootPrint() const { return treeMemoryFootprint() + bitFieldMemoryFootprint(); }
uint32 treeMemoryFootprint() const { return tree.numSlots * sizeof(uint32); }
uint32 bitFieldMemoryFootprint() const { return (tree.numElements / 64) * sizeof(uint64); }
void setBit(uint32 bitID, bool state) {
// Coordinates of the bit
uint32_t slot = bitID / 64;
uint32_t local_id = bitID % 64;
if (state)
bitfield[slot] |= 1ull << local_id;
else
bitfield[slot] &= ~(1ull << local_id);
}
uint32 getBit(uint32 bitID) const {
uint32_t slot = bitID / 64;
uint32_t local_id = bitID % 64;
return (bitfield[slot] & (1ull << local_id)) >> local_id;
}
uint32 bitcount() const { return packedHeap[0]; }
uint32 bitCount(uint32 depth, uint32 element) { return getHeapElement((1 << depth) + element); }
uint32 decodeBit(uint32 handle) const {
uint32_t currentDepth = 0;
uint32_t heapElementID = 1u;
for (currentDepth = 0; currentDepth < tree.firstVirtualLevel; ++currentDepth) {
// Read the left element
uint32_t heapValue = getHeapElement(2u * heapElementID);
// Does it fall in the right or left subtree?
uint32_t b = handle < heapValue ? 0u : 1u;
// Pick a subtree
heapElementID = 2u * heapElementID + b;
// Move the iterator to exclude the right subtree if required
handle -= heapValue * b;
}
// Align with the internal depth
currentDepth++;
// Ok we have our subtree, now we need to pick the right bit
uint64_t heapValue = bitfield[heapElementID - tree.lastLevel * 2];
for (; currentDepth < (tree.leafLevel + 1); ++currentDepth) {
// Figure out the location of the first bit of this element
uint32_t real_heap_id = 2 * heapElementID - 1;
uint32_t level_first_element = (1 << currentDepth) - 1;
uint32_t id_in_level = real_heap_id - level_first_element;
uint32_t first_bit = tree.depthOffset[currentDepth] + tree.bitCount[currentDepth] * id_in_level;
uint32_t local_id = first_bit % 64;
uint64_t target_bits = (heapValue >> local_id) & tree.bitMask[currentDepth];
uint32_t heapValue = std::popcount(target_bits);
// Does it fall in the right or left subtree?
uint32_t b = handle < heapValue ? 0u : 1u;
// Pick a subtree
heapElementID = 2u * heapElementID + b;
// Move the iterator to exclude the right subtree if required
handle -= heapValue * b;
}
return (heapElementID ^ tree.numElements);
}
uint32 decodeBitComplement(uint32 handle) const {
uint32_t heapElementID = 1u;
uint32_t c = tree.numElements / 2u;
uint32_t currentDepth = 0;
for (currentDepth = 0; currentDepth < tree.firstVirtualLevel; ++currentDepth) {
uint32_t heapValue = c - getHeapElement(2u * heapElementID);
uint32_t b = handle < heapValue ? 0u : 1u;
heapElementID = 2u * heapElementID + b;
handle -= heapValue * b;
c /= 2u;
}
// Align with the internal depth
currentDepth++;
// Ok we have our subtree, now we need to pick the right bit
uint64_t heapValue = bitfield[heapElementID - tree.lastLevelSize * 2];
for (; currentDepth < (tree.leafLevel + 1); ++currentDepth) {
// Figure out the location of the first bit of this element
uint32_t real_heap_id = 2 * heapElementID - 1;
uint32_t level_first_element = (1 << currentDepth) - 1;
uint32_t id_in_level = real_heap_id - level_first_element;
uint32_t first_bit = tree.depthOffset[currentDepth] + tree.bitCount[currentDepth] * id_in_level;
uint32_t local_id = first_bit % 64;
uint64_t target_bits = (heapValue >> local_id) & tree.bitMask[currentDepth];
uint32_t heapValue = c - countbits(target_bits);
uint32_t b = handle < heapValue ? 0u : 1u;
heapElementID = 2u * heapElementID + b;
handle -= heapValue * b;
c /= 2u;
}
return (heapElementID ^ tree.numElements);
}
uint32 getHeapElement(uint32 id) const {
// Figure out the location of the first bit of this element
uint32_t real_heap_id = id - 1;
uint32_t depth = uint32_t(log2(real_heap_id + 1));
uint32_t level_first_element = (1 << depth) - 1;
uint32_t id_in_level = real_heap_id - level_first_element;
uint32_t first_bit = tree.depthOffset[depth] + tree.bitCount[depth] * id_in_level;
if (depth < tree.firstVirtualLevel) {
uint32_t slot = first_bit / 32;
uint32_t local_id = first_bit % 32;
uint32_t target_bits = (packedHeap[slot] >> local_id) & tree.bitMask[depth];
return (packedHeap[slot] >> local_id) & tree.bitMask[depth];
} else {
uint32_t slot = first_bit / 64;
uint32_t local_id = first_bit % 64;
uint64_t target_bits = (bitfield[slot] >> local_id) & tree.bitMask[depth];
return std::popcount(target_bits);
}
}
uint32 setHeapElement(uint32 id, uint32 value) {
// Figure out the location of the first bit of this element
uint32_t real_heap_id = id - 1;
uint32_t depth = uint32_t(log2(real_heap_id + 1));
uint32_t level_first_element = (1 << depth) - 1;
uint32_t id_in_level = real_heap_id - level_first_element;
// If this is the tree representation
if (depth < tree.firstVirtualLevel) {
// Find the slot and the local first bit
uint32_t first_bit = tree.depthOffset[depth] + tree.bitCount[depth] * id_in_level;
uint32_t slot = first_bit / 32;
uint32_t local_id = first_bit % 32;
// Extract the relevant bits
uint32_t& target = packedHeap[slot];
target &= ~(tree.bitMask[depth] << (local_id));
target |= (tree.bitMask[depth] & value) << (local_id);
}
// Should be avoided, but is supported
else if (depth == tree.leafLevel) {
setBit(id_in_level, value);
}
// Doesn't make sense
else {
assert(false);
}
}
void reduce() {
// First reduce the last level using countbits
for (uint32_t threadID = 0; threadID < (tree.lastLevelSize / 4); ++threadID) {
// Initialize the packed sum
uint32_t packedSum = 0;
// Loop through the 2 pairs to process
for (uint32_t pairIdx = 0; pairIdx < 4; ++pairIdx) {
// First element of the pair
uint32_t elementC = std::popcount(bitfield[threadID * 8 + 2 * pairIdx]);
// Second element of the pair
elementC += std::popcount(bitfield[threadID * 8 + 2 * pairIdx + 1]);
// Store in the right bits
packedSum |= (elementC << pairIdx * 8);
}
// Offset of the last level of the tree
const uint32_t bufferOffset = tree.depthOffset[11] / 32;
// Store the result into the bitfield
packedHeap[bufferOffset + threadID] = packedSum;
}
// Then operate the reduction on the tree only (not the bitfield)
for (uint32_t size = tree.numElements / 128u; size > 0u; size /= 2u) {
uint32_t minHeapID = size;
uint32_t maxHeapID = size * 2u;
for (uint32_t heapID = minHeapID; heapID < maxHeapID; ++heapID) {
uint32_t value = getHeapElement(2u * heapID) + getHeapElement(2u * heapID + 1u);
setHeapElement(heapID, value);
}
}
}
void clear() {
memset(packedHeap, 0, tree.numSlots * sizeof(uint32_t));
memset(bitfield, 0, tree.bitFieldNumSlots * sizeof(uint64_t));
}
private:
uint32* rawMemory;
uint32* packedHeap;
uint64* bitfield;
};
struct GeometryCB {
uint32 totalNumElements;
uint32 baseDepth;
uint32 totalNumVertices;
};
struct UpdateCB {
float triangleSize;
uint32_t maxSubdivisionDepth;
float fov;
float farPlaneDistance;
};
struct CPUMesh {
uint32 totalNumElements = 0;
uint32 minimalDepth = 0;
Array<uint64> heapIDArray;
Array<UVector4> neighborsArray;
Array<Vector4> basePoints;
};
CPUMesh generateCPUMesh(uint32 cbtNumElements);
// Pointer to an invalid neighbor or index
constexpr uint64 INVALID_POINTER = UINT32_MAX;
// Possible culling state
constexpr int64 BACK_FACE_CULLED = -3;
constexpr int64 FRUSTUM_CULLED = -2;
constexpr int64 TOO_SMALL = -1;
constexpr int64 UNCHANGED_ELEMENT = 0;
constexpr int64 BISECT_ELEMENT = 1;
constexpr int64 SIMPLIFY_ELEMENT = 2;
constexpr int64 MERGED_ELEMENT = 3;
struct BisectorData {
uint32 subdivisionPattern;
UVector indices;
uint32 problematicNeighbor;
uint32 bisectorState;
uint32 flags;
uint32 propagationID;
};
struct LebMatrixCache {
void init(Gfx::PGraphics graphics, uint32 cacheDepth);
void release();
Gfx::PShaderBuffer getLebMatrixBuffer() const { return lebMatrixBuffer; }
private:
Gfx::OShaderBuffer lebMatrixBuffer;
uint32 cacheDepth;
};
struct GPU_CBT {
uint32 numElements;
uint32 lastLevelSize = 0;
uint32 bufferCount = 2;
Gfx::OShaderBuffer bufferArray[2];
};
struct BaseMesh {
uint32 numVertices;
Gfx::OShaderBuffer vertexBuffer;
uint32 numElements;
Gfx::OIndexBuffer indexBuffer;
};
struct CBTMesh {
uint32 totalNumElements;
uint32 numBaseVertices;
uint32 baseDepth;
Gfx::OShaderBuffer heapIDBuffer;
uint32 currentNeighborsBufferIdx;
Gfx::OShaderBuffer neighborsBuffers[2];
Gfx::OShaderBuffer updateBuffer;
Gfx::OShaderBuffer classificationBuffer;
Gfx::OShaderBuffer simplificationBuffer;
Gfx::OShaderBuffer allocateBuffer;
Gfx::OShaderBuffer propagateBuffer;
Gfx::OShaderBuffer indirectDrawBuffer;
Gfx::OShaderBuffer indirectDispatchBuffer;
Gfx::OShaderBuffer indexedBisectorBuffer;
Gfx::OShaderBuffer visibleIndexedBisectorBuffer;
Gfx::OShaderBuffer modifiedIndexedBisectorBuffer;
Gfx::OShaderBuffer lebVertexBuffer;
Gfx::OShaderBuffer currentVertexBuffer;
Gfx::OShaderBuffer currentDisplacementBuffer;
GPU_CBT gpuCBT;
};
struct MeshUpdater {
void init(Gfx::PGraphics gfx, Gfx::PDescriptorLayout viewParamsLayout);
void release();
void evaluateLeb(const BaseMesh& baseMesh, CBTMesh& mesh, Gfx::PDescriptorSet viewParamsSet,
Gfx::PUniformBuffer geometryBuffer, Gfx::PUniformBuffer updateBuffer, Gfx::PShaderBuffer lebMatrixCache, bool clear,
bool complete);
void update(CBTMesh& mesh, Gfx::PDescriptorSet viewParamsSet, Gfx::PUniformBuffer geometryCB, Gfx::PUniformBuffer updateCB);
void validation(const CBTMesh& mesh, Gfx::PUniformBuffer geometryCB);
void resetBuffers(const CBTMesh& mesh);
void prepareIndirection(CBTMesh& mesh, Gfx::PUniformBuffer geometryCB);
bool checkIfValid();
void queryOccupancy(const CBTMesh& mesh);
uint32 getOccupancy();
Gfx::PGraphics graphics;
Gfx::ODescriptorLayout layout;
Gfx::OPipelineLayout pipelineLayout;
Gfx::OShaderBuffer indirectBuffer;
Gfx::OShaderBuffer memoryBuffer;
Gfx::OShaderBuffer validationBuffer;
Gfx::OShaderBuffer validationBufferRB;
Gfx::OShaderBuffer occupancyBufferRB;
// Main update
Gfx::OComputeShader resetCS;
Gfx::PComputePipeline reset;
Gfx::OComputeShader classifyCS;
Gfx::PComputePipeline classify;
Gfx::OComputeShader splitCS;
Gfx::PComputePipeline split;
Gfx::OComputeShader prepareIndirectCS;
Gfx::PComputePipeline prepareIndirect;
Gfx::OComputeShader allocateCS;
Gfx::PComputePipeline allocate;
Gfx::OComputeShader bisectCS;
Gfx::PComputePipeline bisect;
Gfx::OComputeShader propagateBisectCS;
Gfx::PComputePipeline propagateBisect;
Gfx::OComputeShader prepareSimplifyCS;
Gfx::PComputePipeline prepareSimplify;
Gfx::OComputeShader simplifyCS;
Gfx::PComputePipeline simplify;
Gfx::OComputeShader propagateSimplifyCS;
Gfx::PComputePipeline propagateSimplify;
// Reduction
Gfx::OComputeShader reducePrePassCS;
Gfx::PComputePipeline reducePrePass;
Gfx::OComputeShader reduceFirstPassCS;
Gfx::PComputePipeline reduceFirstPass;
Gfx::OComputeShader reduceSecondPassCS;
Gfx::PComputePipeline reduceSecondPass;
// Indexation
Gfx::OComputeShader bisectorIndexationCS;
Gfx::PComputePipeline bisectorIndexation;
Gfx::OComputeShader prepareBisectorIndirectCS;
Gfx::PComputePipeline prepareBisectorIndirect;
// Debug
Gfx::OComputeShader validateCS;
Gfx::PComputePipeline validate;
// LEB
Gfx::OComputeShader lebClearCS;
Gfx::PComputePipeline lebClear;
Gfx::OComputeShader lebEvaluateCS;
Gfx::PComputePipeline lebEvaluate;
};
}; // namespace Seele
+11
View File
@@ -0,0 +1,11 @@
target_sources(Engine
PRIVATE
CBT.h
CBT.cpp
)
target_sources(Engine
PUBLIC FILE_SET HEADERS
FILES
CBT.h
)
+2
View File
@@ -1,3 +1,5 @@
add_subdirectory(CBT/)
target_sources(Engine
PRIVATE
Buffer.h
+2
View File
@@ -19,6 +19,7 @@ class RenderCommand {
virtual void bindIndexBuffer(Gfx::PIndexBuffer indexBuffer) = 0;
virtual void pushConstants(Gfx::SeShaderStageFlags stage, uint32 offset, uint32 size, const void* data) = 0;
virtual void draw(uint32 vertexCount, uint32 instanceCount, int32 firstVertex, uint32 firstInstance) = 0;
virtual void drawIndirect(Gfx::PShaderBuffer buffer, uint64 offset, uint32 drawCount, uint32 stride) = 0;
virtual void drawIndexed(uint32 indexCount, uint32 instanceCount, int32 firstIndex, uint32 vertexOffset, uint32 firstInstance) = 0;
virtual void drawMesh(uint32 groupX, uint32 groupY, uint32 groupZ) = 0;
virtual void drawMeshIndirect(Gfx::PShaderBuffer buffer, uint64 offset, uint32 drawCount, uint32 stride) = 0;
@@ -35,6 +36,7 @@ class ComputeCommand {
virtual void bindDescriptor(const Array<Gfx::PDescriptorSet>& sets) = 0;
virtual void pushConstants(Gfx::SeShaderStageFlags stage, uint32 offset, uint32 size, const void* data) = 0;
virtual void dispatch(uint32 threadX, uint32 threadY, uint32 threadZ) = 0;
virtual void dispatchIndirect(Gfx::PShaderBuffer buffer, uint32 offset) = 0;
std::string name;
};
DEFINE_REF(ComputeCommand)
+1
View File
@@ -65,6 +65,7 @@ class DescriptorSet {
virtual void writeChanges() = 0;
virtual void updateBuffer(uint32 binding, uint32 index, Gfx::PUniformBuffer uniformBuffer) = 0;
virtual void updateBuffer(uint32 binding, uint32 index, Gfx::PShaderBuffer shaderBuffer) = 0;
virtual void updateBuffer(uint32 binding, uint32 index, Gfx::PVertexBuffer indexBuffer) = 0;
virtual void updateBuffer(uint32 binding, uint32 index, Gfx::PIndexBuffer indexBuffer) = 0;
virtual void updateSampler(uint32 binding, uint32 index, Gfx::PSampler samplerState) = 0;
virtual void updateTexture(uint32 binding, uint32 index, Gfx::PTexture2D texture) = 0;
+2
View File
@@ -100,6 +100,8 @@ class Graphics {
virtual void resolveTexture(PTexture source, PTexture destination) = 0;
virtual void copyTexture(PTexture src, PTexture dst) = 0;
virtual void copyBuffer(Gfx::PShaderBuffer src, Gfx::PShaderBuffer dst) = 0;
bool supportMeshShading() const { return meshShadingEnabled; }
// Ray Tracing
+1 -1
View File
@@ -98,7 +98,7 @@ struct ShaderBufferCreateInfo {
uint64 numElements = 1;
uint32 clearValue = 0;
uint8 createCleared = 0;
uint8 vertexBuffer = 0;
Gfx::SeBufferUsageFlags usage = 0;
std::string name = "Unnamed";
};
DECLARE_NAME_REF(Gfx, PipelineLayout)
+6 -5
View File
@@ -27,7 +27,6 @@ void Seele::addDebugVertices(Array<DebugVertex> verts) { gDebugVertices.addAll(v
BasePass::BasePass(Gfx::PGraphics graphics, PScene scene) : RenderPass(graphics, scene) {
//waterRenderer = new WaterRenderer(graphics, scene, viewParamsLayout);
//terrainRenderer = new TerrainRenderer(graphics, scene, viewParamsLayout);
basePassLayout = graphics->createPipelineLayout("BasePassLayout");
basePassLayout->addDescriptorLayout(viewParamsLayout);
@@ -100,7 +99,7 @@ void BasePass::beginFrame(const Component::Camera& cam) {
transparentCulling = lightCullingLayout->allocateDescriptorSet();
//waterRenderer->beginFrame();
//terrainRenderer->beginFrame();
terrainRenderer->beginFrame(viewParamsSet);
// Debug vertices
{
@@ -249,8 +248,8 @@ void BasePass::render() {
}
}
// commands.add(waterRenderer->render(viewParamsSet));
// commands.add(terrainRenderer->render(viewParamsSet));
//commands.add(waterRenderer->render(viewParamsSet));
commands.add(terrainRenderer->render(viewParamsSet));
// Skybox
{
@@ -432,6 +431,8 @@ void BasePass::publishOutputs() {
}
void BasePass::createRenderPass() {
RenderPass::beginFrame(Component::Camera());
terrainRenderer = new TerrainRenderer(graphics, scene, viewParamsLayout, viewParamsSet);
cullingBuffer = resources->requestBuffer("CULLINGBUFFER");
timestamps = resources->requestTimestampQuery("TIMESTAMPS");
@@ -474,7 +475,7 @@ void BasePass::createRenderPass() {
tLightGrid = resources->requestTexture("LIGHTCULLING_TLIGHTGRID");
//waterRenderer->setViewport(viewport, renderPass);
//terrainRenderer->setViewport(viewport, renderPass);
terrainRenderer->setViewport(viewport, renderPass);
// Debug rendering
{
+1 -1
View File
@@ -51,7 +51,7 @@ class BasePass : public RenderPass {
Gfx::PShaderBuffer cullingBuffer;
//OWaterRenderer waterRenderer;
//OTerrainRenderer terrainRenderer;
OTerrainRenderer terrainRenderer;
// Debug rendering
Gfx::OVertexInput debugVertexInput;
@@ -31,13 +31,6 @@ class LightCullingPass : public RenderPass {
glm::uvec3 numThreads;
uint32_t pad1;
} dispatchParams;
struct Plane {
Vector n;
float d;
};
struct Frustum {
Plane planes[4];
};
Gfx::OShaderBuffer frustumBuffer;
Gfx::OUniformBuffer dispatchParamsBuffer;
@@ -23,13 +23,18 @@ RenderPass::RenderPass(Gfx::PGraphics graphics, PScene scene) : graphics(graphic
RenderPass::~RenderPass() {}
void RenderPass::beginFrame(const Component::Camera& cam) {
auto screenDim = Vector2(static_cast<float>(viewport->getWidth()), static_cast<float>(viewport->getHeight()));
viewParams = {
.viewMatrix = cam.getViewMatrix(),
.inverseViewMatrix = glm::inverse(cam.getViewMatrix()),
.projectionMatrix = viewport->getProjectionMatrix(),
.inverseProjection = glm::inverse(viewport->getProjectionMatrix()),
.cameraPosition = Vector4(cam.getCameraPosition(), 1),
.screenDimensions = Vector2(static_cast<float>(viewport->getWidth()), static_cast<float>(viewport->getHeight())),
.cameraPosition_WS = Vector4(cam.getCameraPosition(), 1),
.cameraForward_WS = Vector4(cam.getCameraForward(), 1),
.screenDimensions = screenDim,
.invScreenDimensions = 1.0f / screenDim,
.frameIndex = Gfx::getCurrentFrameIndex(),
.time = static_cast<float>(Gfx::getCurrentFrameTime()),
};
viewParamsBuffer->rotateBuffer(sizeof(ViewParameter));
viewParamsBuffer->updateContents(0, sizeof(ViewParameter), &viewParams);
+13 -1
View File
@@ -27,13 +27,25 @@ class RenderPass {
void setViewport(Gfx::PViewport _viewport);
protected:
struct Plane {
Vector n;
float d;
};
struct Frustum {
Plane planes[4];
};
struct ViewParameter {
Frustum viewFrustum;
Matrix4 viewMatrix;
Matrix4 inverseViewMatrix;
Matrix4 projectionMatrix;
Matrix4 inverseProjection;
Vector4 cameraPosition;
Vector4 cameraPosition_WS;
Vector4 cameraForward_WS;
Vector2 screenDimensions;
Vector2 invScreenDimensions;
uint32 frameIndex;
float time;
} viewParams;
PRenderGraphResources resources;
Gfx::ODescriptorLayout viewParamsLayout;
@@ -2,111 +2,298 @@
#include "Asset/AssetRegistry.h"
#include "Component/TerrainTile.h"
#include "Graphics/Graphics.h"
#include "Graphics/Pipeline.h"
#include "Graphics/Shader.h"
using namespace Seele;
TerrainRenderer::TerrainRenderer(Gfx::PGraphics graphics, PScene scene, Gfx::PDescriptorLayout viewParamsLayout)
TerrainRenderer::TerrainRenderer(Gfx::PGraphics graphics, PScene scene, Gfx::PDescriptorLayout viewParamsLayout,
Gfx::PDescriptorSet viewParamsSet)
: graphics(graphics), scene(scene) {
struct TerrainTile {
IVector2 offset;
float extent;
float height;
};
Array<TerrainTile> payloads;
for (int32 y = -100; y < 100; ++y) {
for (int32 x = -100; x < 100; ++x) {
payloads.add(TerrainTile{
.offset = IVector2(x, y),
.extent = Component::TerrainTile::DIMENSIONS,
.height = 0,
});
}
meshUpdater.init(graphics, viewParamsLayout);
lebCache.init(graphics, 5);
CBT<21> cbt;
CPUMesh cpuMesh = generateCPUMesh(cbt.numElements());
plainMesh.gpuCBT.lastLevelSize = cbt.lastLevelSize();
for (uint32 i = 0; i < 2; ++i) {
uint32 bufferSize = cbt.bufferSize(i);
uint32 elementSize = cbt.elementSize(i);
plainMesh.gpuCBT.bufferArray[i] = graphics->createShaderBuffer(ShaderBufferCreateInfo{
.sourceData =
{
.size = bufferSize,
.data = (uint8*)cbt.rawBuffer(i),
},
.name = "GPUCBT",
});
plainMesh.gpuCBT.bufferArray[i]->pipelineBarrier(Gfx::SE_ACCESS_TRANSFER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT,
Gfx::SE_ACCESS_SHADER_READ_BIT | Gfx::SE_ACCESS_SHADER_WRITE_BIT,
Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
}
tilesBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
plainMesh.totalNumElements = cpuMesh.totalNumElements;
plainMesh.numBaseVertices = (uint32)cpuMesh.basePoints.size();
plainMesh.baseDepth = cpuMesh.minimalDepth;
plainMesh.heapIDBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
.sourceData =
{
.size = sizeof(TerrainTile) * payloads.size(),
.data = (uint8*)payloads.data(),
.size = sizeof(uint64) * cpuMesh.totalNumElements,
.data = (uint8*)cpuMesh.heapIDArray.data(),
},
.numElements = payloads.size(),
.name = "TilesBuffer",
.name = "HeapID",
});
tilesBuffer->pipelineBarrier(Gfx::SE_ACCESS_TRANSFER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT, Gfx::SE_ACCESS_SHADER_READ_BIT,
Gfx::SE_PIPELINE_STAGE_TASK_SHADER_BIT_EXT);
colorMap = AssetRegistry::findTexture("", "azeroth")->getTexture();
displacementMap = AssetRegistry::findTexture("", "azeroth_height")->getTexture();
plainMesh.heapIDBuffer->pipelineBarrier(Gfx::SE_ACCESS_TRANSFER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT,
Gfx::SE_ACCESS_SHADER_READ_BIT | Gfx::SE_ACCESS_SHADER_WRITE_BIT,
Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
sampler = graphics->createSampler(SamplerCreateInfo{});
layout = graphics->createDescriptorLayout("pTerrainData");
layout->addDescriptorBinding(Gfx::DescriptorBinding{
.binding = 0,
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
plainMesh.currentNeighborsBufferIdx = 0;
plainMesh.neighborsBuffers[0] = graphics->createShaderBuffer(ShaderBufferCreateInfo{
.sourceData =
{
.size = sizeof(UVector4) * cpuMesh.totalNumElements,
.data = (uint8*)cpuMesh.neighborsArray.data(),
},
.name = "Neighbours0",
});
layout->addDescriptorBinding(Gfx::DescriptorBinding{
.binding = 1,
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
plainMesh.neighborsBuffers[0]->pipelineBarrier(Gfx::SE_ACCESS_TRANSFER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT,
Gfx::SE_ACCESS_SHADER_READ_BIT | Gfx::SE_ACCESS_SHADER_WRITE_BIT,
Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
plainMesh.neighborsBuffers[1] = graphics->createShaderBuffer(ShaderBufferCreateInfo{
.sourceData =
{
.size = sizeof(UVector4) * cpuMesh.totalNumElements,
},
.name = "Neighbours1",
});
layout->addDescriptorBinding(Gfx::DescriptorBinding{
.binding = 2,
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
plainMesh.neighborsBuffers[1]->pipelineBarrier(Gfx::SE_ACCESS_TRANSFER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT,
Gfx::SE_ACCESS_SHADER_READ_BIT | Gfx::SE_ACCESS_SHADER_WRITE_BIT,
Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
plainMesh.updateBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
.sourceData =
{
.size = sizeof(BisectorData) * cpuMesh.totalNumElements,
},
.usage = Gfx::SE_BUFFER_USAGE_INDIRECT_BUFFER_BIT,
.name = "UpdateBuffer",
});
layout->addDescriptorBinding(Gfx::DescriptorBinding{
.binding = 3,
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_SAMPLER,
plainMesh.classificationBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
.sourceData =
{
.size = sizeof(uint32) * (2 + cpuMesh.totalNumElements * 2),
},
.name = "Classification",
});
layout->create();
pipelineLayout = graphics->createPipelineLayout("TerrainLayout");
pipelineLayout->addDescriptorLayout(viewParamsLayout);
pipelineLayout->addDescriptorLayout(layout);
ShaderCompilationInfo s{
.name = "TerrainShaders",
plainMesh.simplificationBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
.sourceData =
{
.size = sizeof(uint32) * (1 + cpuMesh.totalNumElements),
},
.name = "Simplification",
});
plainMesh.allocateBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
.sourceData =
{
.size = sizeof(uint32) * (1 + cpuMesh.totalNumElements),
},
.name = "Allocation",
});
plainMesh.propagateBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
.sourceData =
{
.size = sizeof(uint32) * (2 + cpuMesh.totalNumElements),
},
.name = "Propagate",
});
plainMesh.indirectDrawBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
.sourceData =
{
.size = sizeof(uint32) * (4 * 2 + 2),
},
.usage = Gfx::SE_BUFFER_USAGE_INDIRECT_BUFFER_BIT,
.name = "IndirectDraw",
});
plainMesh.indirectDispatchBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
.sourceData =
{
.size = sizeof(uint32) * 3 * 3,
},
.usage = Gfx::SE_BUFFER_USAGE_INDIRECT_BUFFER_BIT,
.name = "IndirectDispatch",
});
plainMesh.indexedBisectorBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
.sourceData =
{
.size = sizeof(uint32) * cpuMesh.totalNumElements,
},
.name = "IndexedBisector",
});
plainMesh.visibleIndexedBisectorBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
.sourceData =
{
.size = sizeof(uint32) * cpuMesh.totalNumElements,
},
.name = "VisibleIndexedBisector",
});
plainMesh.modifiedIndexedBisectorBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
.sourceData =
{
.size = sizeof(uint32) * cpuMesh.totalNumElements,
},
.name = "ModifiedIndexedBisector",
});
plainMesh.lebVertexBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
.sourceData =
{
.size = sizeof(Vector4) * plainMesh.totalNumElements * 4,
},
.name = "LebVertexBuffer",
});
plainMesh.currentVertexBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
.sourceData =
{
.size = sizeof(Vector4) * plainMesh.totalNumElements * 4,
},
.usage = Gfx::SE_BUFFER_USAGE_INDIRECT_BUFFER_BIT,
.name = "CurrentVertexBuffer",
});
plainMesh.currentDisplacementBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
.sourceData =
{
.size = sizeof(Vector4) * plainMesh.totalNumElements * 3,
},
.name = "CurrentDisplacementBuffer",
});
uint32 numBaseVertex = (uint32)cpuMesh.basePoints.size();
baseMesh.numVertices = numBaseVertex;
baseMesh.numElements = numBaseVertex / 3;
uint32 baseVertexBufferSize = sizeof(Vector4) * numBaseVertex;
baseMesh.vertexBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
.sourceData =
{
.size = baseVertexBufferSize,
.data = (uint8*)cpuMesh.basePoints.data(),
},
.name = "VertexBuffer",
});
baseMesh.vertexBuffer->pipelineBarrier(Gfx::SE_ACCESS_TRANSFER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT,
Gfx::SE_ACCESS_SHADER_READ_BIT | Gfx::SE_ACCESS_SHADER_WRITE_BIT,
Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
uint32 indexBufferSize = cpuMesh.totalNumElements * sizeof(UVector);
Array<uint32> indices;
for (uint32 i = 0; i < cpuMesh.totalNumElements * 3; ++i)
indices.add(i);
baseMesh.indexBuffer = graphics->createIndexBuffer(IndexBufferCreateInfo{
.sourceData =
{
.size = sizeof(uint32) * indices.size(),
.data = (uint8*)indices.data(),
},
.indexType = Gfx::SE_INDEX_TYPE_UINT32,
.name = "IndexBuffer",
});
baseMesh.indexBuffer->pipelineBarrier(Gfx::SE_ACCESS_TRANSFER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT,
Gfx::SE_ACCESS_SHADER_READ_BIT | Gfx::SE_ACCESS_SHADER_WRITE_BIT,
Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
GeometryCB geometryCB = {
.totalNumElements = plainMesh.totalNumElements,
.baseDepth = plainMesh.baseDepth,
.totalNumVertices = plainMesh.totalNumElements * 3,
};
geometryBuffer = graphics->createUniformBuffer(UniformBufferCreateInfo{
.sourceData =
{
.size = sizeof(GeometryCB),
.data = (uint8*)&geometryCB,
},
.name = "GeometryCB",
});
geometryBuffer->pipelineBarrier(Gfx::SE_ACCESS_TRANSFER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT, Gfx::SE_ACCESS_UNIFORM_READ_BIT,
Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
UpdateCB updateCB = {
.triangleSize = 10.0f,
.maxSubdivisionDepth = 63,
.fov = 70.0f,
.farPlaneDistance = 1000.0f,
};
updateBuffer = graphics->createUniformBuffer(UniformBufferCreateInfo{
.sourceData =
{
.size = sizeof(UpdateCB),
.data = (uint8*)&updateCB,
},
.name = "UpdateCB",
});
updateBuffer->pipelineBarrier(Gfx::SE_ACCESS_TRANSFER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT, Gfx::SE_ACCESS_UNIFORM_READ_BIT,
Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
meshUpdater.resetBuffers(plainMesh);
meshUpdater.prepareIndirection(plainMesh, geometryBuffer);
meshUpdater.evaluateLeb(baseMesh, plainMesh, viewParamsSet, geometryBuffer, updateBuffer, lebCache.getLebMatrixBuffer(), true, true);
graphics->beginShaderCompilation(ShaderCompilationInfo{
.modules = {"TerrainPass"},
.entryPoints =
{
{"taskMain", "TerrainPass"},
{"meshMain", "TerrainPass"},
{"fragmentMain", "TerrainPass"},
{"vert", "TerrainPass"},
{"frag", "TerrainPass"},
{"deform", "TerrainPass"},
},
.rootSignature = pipelineLayout,
.dumpIntermediate = false,
};
graphics->beginShaderCompilation(s);
task = graphics->createTaskShader({0});
mesh = graphics->createMeshShader({1});
frag = graphics->createFragmentShader({2});
pipelineLayout->create();
.rootSignature = meshUpdater.pipelineLayout,
});
vert = graphics->createVertexShader({0});
frag = graphics->createFragmentShader({1});
deformCS = graphics->createComputeShader({2});
deform = graphics->createComputePipeline(Gfx::ComputePipelineCreateInfo{
.computeShader = deformCS,
.pipelineLayout = meshUpdater.pipelineLayout,
});
}
TerrainRenderer::~TerrainRenderer() {}
void TerrainRenderer::beginFrame() {
set = layout->allocateDescriptorSet();
set->updateBuffer(0, 0, tilesBuffer);
set->updateTexture(1, 0, displacementMap);
set->updateTexture(2, 0, colorMap);
set->updateSampler(3, 0, sampler);
void TerrainRenderer::beginFrame(Gfx::PDescriptorSet viewParamsSet) {
meshUpdater.update(plainMesh, viewParamsSet, geometryBuffer, updateBuffer);
meshUpdater.evaluateLeb(baseMesh, plainMesh, viewParamsSet, geometryBuffer, updateBuffer, lebCache.getLebMatrixBuffer(), false, false);
Gfx::PDescriptorSet set = meshUpdater.layout->allocateDescriptorSet();
set->updateBuffer(GEOMETRY_CB, 0, geometryBuffer);
set->updateBuffer(INDIRECT_DRAW_BUFFER, 0, plainMesh.indirectDrawBuffer);
set->updateBuffer(INDEXED_BISECTOR_BUFFER, 0, plainMesh.indexedBisectorBuffer);
set->updateBuffer(LEB_POSITION_BUFFER, 0, plainMesh.lebVertexBuffer);
set->updateBuffer(CURRENT_VERTEX_BUFFER, 0, plainMesh.currentVertexBuffer);
set->writeChanges();
Gfx::OComputeCommand command = graphics->createComputeCommand("Deform");
command->bindPipeline(deform);
command->bindDescriptor({viewParamsSet, set});
command->dispatchIndirect(plainMesh.indirectDispatchBuffer, 3 * sizeof(uint32));
graphics->executeCommands(std::move(command));
plainMesh.currentVertexBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_VERTEX_SHADER_BIT);
}
Gfx::ORenderCommand TerrainRenderer::render(Gfx::PDescriptorSet viewParamsSet) {
Gfx::PDescriptorSet set = meshUpdater.layout->allocateDescriptorSet();
set->updateBuffer(CURRENT_VERTEX_BUFFER, 0, plainMesh.currentVertexBuffer);
set->updateBuffer(INDEXED_BISECTOR_BUFFER, 0, plainMesh.indexedBisectorBuffer);
set->writeChanges();
Gfx::ORenderCommand command = graphics->createRenderCommand("TerrainRender");
command->setViewport(viewport);
command->bindPipeline(pipeline);
command->bindDescriptor({viewParamsSet, set});
command->drawMesh(tilesBuffer->getNumElements(), 4, 1);
command->drawIndirect(plainMesh.indirectDrawBuffer, 0, 1, 0);
return command;
}
void TerrainRenderer::setViewport(Gfx::PViewport _viewport, Gfx::PRenderPass renderPass) {
viewport = _viewport;
Gfx::MeshPipelineCreateInfo pipelineInfo = {
.taskShader = task,
.meshShader = mesh,
inp = graphics->createVertexInput({});
Gfx::LegacyPipelineCreateInfo pipelineInfo = {
.vertexInput = inp,
.vertexShader = vert,
.fragmentShader = frag,
.renderPass = renderPass,
.pipelineLayout = pipelineLayout,
.pipelineLayout = meshUpdater.pipelineLayout,
.multisampleState =
{
.samples = viewport->getSamples(),
@@ -128,4 +315,4 @@ void TerrainRenderer::setViewport(Gfx::PViewport _viewport, Gfx::PRenderPass ren
},
};
pipeline = graphics->createGraphicsPipeline(std::move(pipelineInfo));
}
}
@@ -1,12 +1,14 @@
#pragma once
#include "RenderPass.h"
#include "Graphics/Buffer.h"
#include "Graphics/CBT/CBT.h"
namespace Seele {
class TerrainRenderer {
public:
TerrainRenderer(Gfx::PGraphics graphics, PScene scene, Gfx::PDescriptorLayout viewParamsLayout);
TerrainRenderer(Gfx::PGraphics graphics, PScene scene, Gfx::PDescriptorLayout viewParamsLayout, Gfx::PDescriptorSet viewParamsSet);
~TerrainRenderer();
void beginFrame();
void beginFrame(Gfx::PDescriptorSet viewParamsSet);
Gfx::ORenderCommand render(Gfx::PDescriptorSet viewParamsSet);
void setViewport(Gfx::PViewport viewport, Gfx::PRenderPass renderPass);
@@ -18,13 +20,24 @@ class TerrainRenderer {
Gfx::OPipelineLayout pipelineLayout;
Gfx::OTaskShader task;
Gfx::OMeshShader mesh;
Gfx::OVertexInput inp;
Gfx::OVertexShader vert;
Gfx::OFragmentShader frag;
Gfx::PGraphicsPipeline pipeline;
Gfx::OComputeShader deformCS;
Gfx::PComputePipeline deform;
Gfx::PViewport viewport;
Gfx::OShaderBuffer tilesBuffer;
Gfx::PTexture2D displacementMap;
Gfx::PTexture2D colorMap;
Gfx::OSampler sampler;
Gfx::OUniformBuffer geometryBuffer;
Gfx::OUniformBuffer updateBuffer;
BaseMesh baseMesh;
CBTMesh plainMesh;
MeshUpdater meshUpdater;
LebMatrixCache lebCache;
};
DEFINE_REF(TerrainRenderer);
}
} // namespace Seele
@@ -149,7 +149,6 @@ void StaticMeshVertexData::updateBuffers() {
.size = verticesAllocated * sizeof(Vector),
.data = (uint8*)posData.data(),
},
.vertexBuffer = true,
.name = "Positions",
});
normals = graphics->createShaderBuffer(ShaderBufferCreateInfo{
@@ -158,7 +157,6 @@ void StaticMeshVertexData::updateBuffers() {
.size = verticesAllocated * sizeof(Quaternion),
.data = (uint8*)norData.data(),
},
.vertexBuffer = false,
.name = "Normals",
});
colors = graphics->createShaderBuffer(ShaderBufferCreateInfo{
@@ -167,7 +165,6 @@ void StaticMeshVertexData::updateBuffers() {
.size = verticesAllocated * sizeof(U16Vector),
.data = (uint8*)colData.data(),
},
.vertexBuffer = false,
.name = "Colors",
});
for (size_t i = 0; i < MAX_TEXCOORDS; ++i) {
@@ -177,7 +174,6 @@ void StaticMeshVertexData::updateBuffers() {
.size = verticesAllocated * sizeof(U16Vector2),
.data = (uint8*)texData[i].data(),
},
.vertexBuffer = false,
.name = "TexCoords",
});
}
+1 -1
View File
@@ -11,7 +11,7 @@
using namespace Seele;
constexpr static uint64 NUM_DEFAULT_ELEMENTS = 100000;
constexpr static uint64 NUM_DEFAULT_ELEMENTS = 36;
uint64 VertexData::meshletCount = 0;
void VertexData::resetMeshData() {
+7 -11
View File
@@ -389,8 +389,8 @@ void Buffer::pipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcSt
UniformBuffer::UniformBuffer(PGraphics graphics, const UniformBufferCreateInfo& createInfo)
: Gfx::UniformBuffer(graphics->getFamilyMapping(), createInfo),
Vulkan::Buffer(graphics, createInfo.sourceData.size, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, createInfo.sourceData.owner,
true, createInfo.name) {
Vulkan::Buffer(graphics, createInfo.sourceData.size, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, createInfo.sourceData.owner, true,
createInfo.name) {
if (createInfo.sourceData.size > 0 && createInfo.sourceData.data != nullptr) {
getAlloc()->updateContents(createInfo.sourceData.offset, createInfo.sourceData.size, createInfo.sourceData.data);
}
@@ -416,11 +416,7 @@ void UniformBuffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineSt
ShaderBuffer::ShaderBuffer(PGraphics graphics, const ShaderBufferCreateInfo& createInfo)
: Gfx::ShaderBuffer(graphics->getFamilyMapping(), createInfo),
Vulkan::Buffer(graphics, createInfo.sourceData.size,
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
(createInfo.vertexBuffer ? VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR |
VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT
: 0),
Vulkan::Buffer(graphics, createInfo.sourceData.size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | createInfo.usage,
createInfo.sourceData.owner, true, createInfo.name, createInfo.createCleared, createInfo.clearValue) {
if (createInfo.sourceData.size > 0 && createInfo.sourceData.data != nullptr) {
getAlloc()->updateContents(createInfo.sourceData.offset, createInfo.sourceData.size, createInfo.sourceData.data);
@@ -491,12 +487,12 @@ void VertexBuffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineSta
IndexBuffer::IndexBuffer(PGraphics graphics, const IndexBufferCreateInfo& createInfo)
: Gfx::IndexBuffer(graphics->getFamilyMapping(), createInfo),
Vulkan::Buffer(graphics, createInfo.sourceData.size,
VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR |
VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT |
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
createInfo.sourceData.owner, false, createInfo.name) {
getAlloc()->updateContents(createInfo.sourceData.offset, createInfo.sourceData.size, createInfo.sourceData.data);
getAlloc()->pipelineBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT, Gfx::SE_ACCESS_INDEX_READ_BIT,
Gfx::SE_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR | Gfx::SE_PIPELINE_STAGE_VERTEX_INPUT_BIT);
//getAlloc()->pipelineBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT, Gfx::SE_ACCESS_INDEX_READ_BIT,
// Gfx::SE_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR | Gfx::SE_PIPELINE_STAGE_VERTEX_INPUT_BIT);
}
IndexBuffer::~IndexBuffer() {}
+9
View File
@@ -331,6 +331,11 @@ void RenderCommand::draw(uint32 vertexCount, uint32 instanceCount, int32 firstVe
vkCmdDraw(handle, vertexCount, instanceCount, firstVertex, firstInstance);
}
void RenderCommand::drawIndirect(Gfx::PShaderBuffer buffer, uint64 offset, uint32 drawCount, uint32 stride) {
assert(threadId == std::this_thread::get_id());
vkCmdDrawIndirect(handle, buffer.cast<ShaderBuffer>()->getHandle(), offset, drawCount, stride);
}
void RenderCommand::drawIndexed(uint32 indexCount, uint32 instanceCount, int32 firstIndex, uint32 vertexOffset, uint32 firstInstance) {
assert(threadId == std::this_thread::get_id());
vkCmdDrawIndexed(handle, indexCount, instanceCount, firstIndex, vertexOffset, firstInstance);
@@ -470,6 +475,10 @@ void ComputeCommand::dispatch(uint32 threadX, uint32 threadY, uint32 threadZ) {
assert(threadId == std::this_thread::get_id());
vkCmdDispatch(handle, threadX, threadY, threadZ);
}
void ComputeCommand::dispatchIndirect(Gfx::PShaderBuffer buffer, uint32 offset) {
assert(threadId == std::this_thread::get_id());
vkCmdDispatchIndirect(handle, buffer.cast<ShaderBuffer>()->getHandle(), offset);
}
CommandPool::CommandPool(PGraphics graphics, PQueue queue) : graphics(graphics), queue(queue), queueFamilyIndex(queue->getFamilyIndex()) {
VkCommandPoolCreateInfo info = {
+2
View File
@@ -84,6 +84,7 @@ class RenderCommand : public Gfx::RenderCommand {
virtual void bindIndexBuffer(Gfx::PIndexBuffer indexBuffer) override;
virtual void pushConstants(Gfx::SeShaderStageFlags stage, uint32 offset, uint32 size, const void* data) override;
virtual void draw(uint32 vertexCount, uint32 instanceCount, int32 firstVertex, uint32 firstInstance) override;
virtual void drawIndirect(Gfx::PShaderBuffer buffer, uint64 offset, uint32 drawCount, uint32 stride) override;
virtual void drawIndexed(uint32 indexCount, uint32 instanceCount, int32 firstIndex, uint32 vertexOffset, uint32 firstInstance) override;
virtual void drawMesh(uint32 groupX, uint32 groupY, uint32 groupZ) override;
virtual void drawMeshIndirect(Gfx::PShaderBuffer buffer, uint64 offset, uint32 drawCount, uint32 stride) override;
@@ -118,6 +119,7 @@ class ComputeCommand : public Gfx::ComputeCommand {
virtual void bindDescriptor(const Array<Gfx::PDescriptorSet>& sets) override;
virtual void pushConstants(Gfx::SeShaderStageFlags stage, uint32 offset, uint32 size, const void* data) override;
virtual void dispatch(uint32 threadX, uint32 threadY, uint32 threadZ) override;
virtual void dispatchIndirect(Gfx::PShaderBuffer buffer, uint32 offset) override;
private:
PComputePipeline pipeline;
+25
View File
@@ -220,6 +220,31 @@ void DescriptorSet::updateBuffer(uint32_t binding, uint32 index, Gfx::PShaderBuf
boundResources[binding][index] = vulkanBuffer->getAlloc();
}
void DescriptorSet::updateBuffer(uint32_t binding, uint32 index, Gfx::PVertexBuffer indexBuffer) {
PVertexBuffer vulkanBuffer = indexBuffer.cast<VertexBuffer>();
if (boundResources[binding][index] == vulkanBuffer->getAlloc()) {
return;
}
bufferInfos.add(VkDescriptorBufferInfo{
.buffer = vulkanBuffer->getHandle(),
.offset = 0,
.range = vulkanBuffer->getSize(),
});
writeDescriptors.add(VkWriteDescriptorSet{
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
.pNext = nullptr,
.dstSet = setHandle,
.dstBinding = binding,
.dstArrayElement = index,
.descriptorCount = 1,
.descriptorType = cast(layout->getBindings()[binding].descriptorType),
.pBufferInfo = &bufferInfos.back(),
});
boundResources[binding][index] = vulkanBuffer->getAlloc();
}
void DescriptorSet::updateBuffer(uint32_t binding, uint32 index, Gfx::PIndexBuffer indexBuffer) {
PIndexBuffer vulkanBuffer = indexBuffer.cast<IndexBuffer>();
if (boundResources[binding][index] == vulkanBuffer->getAlloc()) {
+1
View File
@@ -50,6 +50,7 @@ class DescriptorSet : public Gfx::DescriptorSet, public CommandBoundResource {
virtual void writeChanges() override;
virtual void updateBuffer(uint32 binding, uint32 index, Gfx::PUniformBuffer uniformBuffer) override;
virtual void updateBuffer(uint32 binding, uint32 index, Gfx::PShaderBuffer shaderBuffer) override;
virtual void updateBuffer(uint32 binding, uint32 index, Gfx::PVertexBuffer indexBuffer) override;
virtual void updateBuffer(uint32 binding, uint32 index, Gfx::PIndexBuffer indexBuffer) override;
virtual void updateSampler(uint32 binding, uint32 index, Gfx::PSampler samplerState) override;
virtual void updateTexture(uint32 binding, uint32 index, Gfx::PTexture2D texture) override;
+17 -4
View File
@@ -377,6 +377,19 @@ void Graphics::copyTexture(Gfx::PTexture source, Gfx::PTexture destination) {
Gfx::SE_ACCESS_MEMORY_READ_BIT | Gfx::SE_ACCESS_MEMORY_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
}
void Graphics::copyBuffer(Gfx::PShaderBuffer srcBuffer, Gfx::PShaderBuffer dstBuffer) {
PShaderBuffer src = srcBuffer.cast<ShaderBuffer>();
PShaderBuffer dst = dstBuffer.cast<ShaderBuffer>();
VkBufferCopy region = {
.srcOffset = 0,
.dstOffset = 0,
.size = src->getSize(),
};
vkCmdCopyBuffer(getGraphicsCommands()->getCommands()->getHandle(), src->getHandle(), dst->getHandle(), 1, &region);
}
Gfx::OBottomLevelAS Graphics::createBottomLevelAccelerationStructure(const Gfx::BottomLevelASCreateInfo& createInfo) {
return new BottomLevelAS(this, createInfo);
}
@@ -740,7 +753,7 @@ void Graphics::pickPhysicalDevice() {
};
meshShaderFeatures = {
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_FEATURES_EXT,
.pNext = &accelerationFeatures,
.pNext = nullptr,
.taskShader = true,
.meshShader = true,
.meshShaderQueries = true,
@@ -872,9 +885,9 @@ void Graphics::createDevice(GraphicsInitializer initializer) {
#ifdef __APPLE__
initializer.deviceExtensions.add("VK_KHR_portability_subset");
#endif
initializer.deviceExtensions.add(VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME);
initializer.deviceExtensions.add(VK_KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME);
initializer.deviceExtensions.add(VK_KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME);
//initializer.deviceExtensions.add(VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME);
//initializer.deviceExtensions.add(VK_KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME);
//initializer.deviceExtensions.add(VK_KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME);
VkDeviceCreateInfo deviceInfo = {
.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
.pNext = &features,
+2
View File
@@ -78,6 +78,8 @@ class Graphics : public Gfx::Graphics {
virtual void resolveTexture(Gfx::PTexture source, Gfx::PTexture destination) override;
virtual void copyTexture(Gfx::PTexture src, Gfx::PTexture dst) override;
virtual void copyBuffer(Gfx::PShaderBuffer src, Gfx::PShaderBuffer dst) override;
// Ray Tracing
virtual Gfx::OBottomLevelAS createBottomLevelAccelerationStructure(const Gfx::BottomLevelASCreateInfo& createInfo) override;
+2 -2
View File
@@ -49,7 +49,7 @@ PGraphicsPipeline PipelineCache::createPipeline(Gfx::LegacyPipelineCreateInfo gf
if (graphicsPipelines.contains(hash)) {
return graphicsPipelines[hash];
}
PPipelineLayout layout = Gfx::PPipelineLayout(gfxInfo.pipelineLayout).cast<PipelineLayout>();
PPipelineLayout layout = gfxInfo.pipelineLayout.cast<PipelineLayout>();
Array<VkVertexInputBindingDescription> bindings;
Array<VkVertexInputAttributeDescription> attributes;
if (gfxInfo.vertexInput != nullptr) {
@@ -429,7 +429,7 @@ PGraphicsPipeline PipelineCache::createPipeline(Gfx::MeshPipelineCreateInfo gfxI
}
PComputePipeline PipelineCache::createPipeline(Gfx::ComputePipelineCreateInfo computeInfo) {
PPipelineLayout layout = Gfx::PPipelineLayout(computeInfo.pipelineLayout).cast<PipelineLayout>();
PPipelineLayout layout = computeInfo.pipelineLayout.cast<PipelineLayout>();
auto computeStage = computeInfo.computeShader.cast<ComputeShader>();
uint32 hash = layout->getHash();
+1 -1
View File
@@ -14,7 +14,7 @@ double Gfx::getCurrentFrameDelta() { return currentFrameDelta; }
double currentFrameTime = 0;
double Gfx::getCurrentFrameTime() { return currentFrameTime; }
uint32 currentFrameIndex = 0;
uint32 currentFrameIndex = std::numeric_limits<uint32>::max();
uint32 Gfx::getCurrentFrameIndex() { return currentFrameIndex; }
void glfwKeyCallback(GLFWwindow* handle, int key, int, int action, int modifier) {
+52 -26
View File
@@ -33,22 +33,48 @@ void Seele::beginCompilation(const ShaderCompilationInfo& info, SlangCompileTarg
}
slang::SessionDesc sessionDesc;
sessionDesc.flags = 0;
StaticArray<slang::CompilerOptionEntry, 5> option;
option[0].name = slang::CompilerOptionName::IgnoreCapabilities;
option[0].value.kind = slang::CompilerOptionValueKind::Int;
option[0].value.intValue0 = 1;
option[1].name = slang::CompilerOptionName::EmitSpirvViaGLSL;
option[1].value.kind = slang::CompilerOptionValueKind::Int;
option[1].value.intValue0 = 1;
option[2].name = slang::CompilerOptionName::DebugInformation;
option[2].value.kind = slang::CompilerOptionValueKind::Int;
option[2].value.intValue0 = SLANG_DEBUG_INFO_LEVEL_STANDARD;
option[3].name = slang::CompilerOptionName::DebugInformationFormat;
option[3].value.kind = slang::CompilerOptionValueKind::Int;
option[3].value.intValue0 = SLANG_DEBUG_INFO_FORMAT_PDB;
option[4].name = slang::CompilerOptionName::DumpIntermediates;
option[4].value.kind = slang::CompilerOptionValueKind::Int;
option[4].value.intValue0 = info.dumpIntermediate;
Array<slang::CompilerOptionEntry> option = {
{
.name = slang::CompilerOptionName::IgnoreCapabilities,
.value =
{
.kind = slang::CompilerOptionValueKind::Int,
.intValue0 = 1,
},
},
{
.name = slang::CompilerOptionName::EmitSpirvViaGLSL,
.value =
{
.kind = slang::CompilerOptionValueKind::Int,
.intValue0 = 1,
},
},
{
.name = slang::CompilerOptionName::DebugInformation,
.value =
{
.kind = slang::CompilerOptionValueKind::Int,
.intValue0 = SLANG_DEBUG_INFO_LEVEL_STANDARD,
},
},
{
.name = slang::CompilerOptionName::DebugInformationFormat,
.value =
{
.kind = slang::CompilerOptionValueKind::Int,
.intValue0 = SLANG_DEBUG_INFO_FORMAT_PDB,
},
},
{
.name = slang::CompilerOptionName::DumpIntermediates,
.value =
{
.kind = slang::CompilerOptionValueKind::Int,
.intValue0 = info.dumpIntermediate,
},
},
};
sessionDesc.compilerOptionEntries = option.data();
sessionDesc.compilerOptionEntryCount = option.size();
@@ -63,11 +89,11 @@ void Seele::beginCompilation(const ShaderCompilationInfo& info, SlangCompileTarg
sessionDesc.preprocessorMacroCount = macros.size();
sessionDesc.preprocessorMacros = macros.data();
slang::TargetDesc targetDesc;
targetDesc.profile = globalSession->findProfile("spirv_1_5");
targetDesc.profile = globalSession->findProfile("GLSL_450");
targetDesc.format = target;
sessionDesc.targetCount = 1;
sessionDesc.targets = &targetDesc;
StaticArray<const char*, 4> searchPaths = {"shaders/", "shaders/lib/", "shaders/raytracing/", "shaders/generated/"};
StaticArray<const char*, 5> searchPaths = {"shaders/", "shaders/lib/", "shaders/raytracing/", "shaders/terrain", "shaders/generated/"};
sessionDesc.searchPaths = searchPaths.data();
sessionDesc.searchPathCount = searchPaths.size();
@@ -113,20 +139,20 @@ void Seele::beginCompilation(const ShaderCompilationInfo& info, SlangCompileTarg
slang::ProgramLayout* signature = specializedComponent->getLayout(0, diagnostics.writeRef());
CHECK_DIAGNOSTICS();
//std::cout << info.name << std::endl;
// std::cout << info.name << std::endl;
for (size_t i = 0; i < signature->getParameterCount(); ++i) {
auto param = signature->getParameterByIndex(i);
layout->addMapping(param->getName(), param->getBindingIndex());
//std::cout << param->getName() << ": " << param->getBindingIndex() << std::endl;
// std::cout << param->getName() << ": " << param->getBindingIndex() << std::endl;
}
// workaround
//layout->addMapping("pVertexData", 1);
//layout->addMapping("pMaterial", 4);
//layout->addMapping("pLightEnv", 3);
//layout->addMapping("pRayTracingParams", 5);
//layout->addMapping("pScene", 2);
//layout->addMapping("pWaterMaterial", 1);
// layout->addMapping("pVertexData", 1);
// layout->addMapping("pMaterial", 4);
// layout->addMapping("pLightEnv", 3);
// layout->addMapping("pRayTracingParams", 5);
// layout->addMapping("pScene", 2);
// layout->addMapping("pWaterMaterial", 1);
}
Pair<Slang::ComPtr<slang::IBlob>, std::string> Seele::generateShader(const ShaderCreateInfo& createInfo) {