More mesh shading changes
This commit is contained in:
@@ -36,7 +36,14 @@ BasePass::BasePass(Gfx::PGraphics graphics, PScene scene)
|
||||
lightCullingLayout->create();
|
||||
|
||||
basePassLayout->addDescriptorLayout(INDEX_LIGHT_CULLING, lightCullingLayout);
|
||||
graphics->getShaderCompiler()->registerRenderPass("BasePass", "LegacyBasePass", true, true, "BasePass");
|
||||
if (graphics->supportMeshShading())
|
||||
{
|
||||
graphics->getShaderCompiler()->registerRenderPass("BasePass", "MeshletBasePass", true, true, "BasePass", true, true, "MeshletBasePass");
|
||||
}
|
||||
else
|
||||
{
|
||||
graphics->getShaderCompiler()->registerRenderPass("BasePass", "LegacyBasePass", true, true, "BasePass");
|
||||
}
|
||||
}
|
||||
|
||||
BasePass::~BasePass()
|
||||
@@ -124,6 +131,7 @@ void BasePass::render()
|
||||
pipelineInfo.pipelineLayout = std::move(layout);
|
||||
pipelineInfo.renderPass = renderPass;
|
||||
pipelineInfo.depthStencilState.depthCompareOp = Gfx::SE_COMPARE_OP_LESS_OR_EQUAL;
|
||||
pipelineInfo.rasterizationState.lineWidth = 10.f;
|
||||
Gfx::PGraphicsPipeline pipeline = graphics->createGraphicsPipeline(std::move(pipelineInfo));
|
||||
command->bindPipeline(pipeline);
|
||||
}
|
||||
|
||||
@@ -20,7 +20,14 @@ DepthPrepass::DepthPrepass(Gfx::PGraphics graphics, PScene scene)
|
||||
|
||||
depthPrepassLayout = graphics->createPipelineLayout();
|
||||
depthPrepassLayout->addDescriptorLayout(INDEX_VIEW_PARAMS, viewParamsLayout);
|
||||
graphics->getShaderCompiler()->registerRenderPass("DepthPass", "LegacyBasePass");
|
||||
if (graphics->supportMeshShading())
|
||||
{
|
||||
graphics->getShaderCompiler()->registerRenderPass("DepthPass", "MeshletBasePass", false, false, "", true, true, "MeshletBasePass");
|
||||
}
|
||||
else
|
||||
{
|
||||
graphics->getShaderCompiler()->registerRenderPass("DepthPass", "LegacyBasePass");
|
||||
}
|
||||
}
|
||||
|
||||
DepthPrepass::~DepthPrepass()
|
||||
|
||||
@@ -111,7 +111,7 @@ void StaticMeshVertexData::deserializeMesh(MeshId id, ArchiveBuffer& buffer)
|
||||
loadNormals(id, nor);
|
||||
loadTangents(id, tan);
|
||||
loadBiTangents(id, bit);
|
||||
loadBiTangents(id, col);
|
||||
loadColors(id, col);
|
||||
}
|
||||
|
||||
void StaticMeshVertexData::init(Gfx::PGraphics graphics)
|
||||
|
||||
@@ -6,10 +6,11 @@
|
||||
#include "Graphics/Descriptor.h"
|
||||
#include "Component/Mesh.h"
|
||||
#include "Graphics/Shader.h"
|
||||
#include <set>
|
||||
|
||||
using namespace Seele;
|
||||
|
||||
constexpr static uint64 NUM_DEFAULT_ELEMENTS = 1024 * 1024;
|
||||
constexpr static uint64 NUM_DEFAULT_ELEMENTS = 16 * 1024;
|
||||
|
||||
void VertexData::resetMeshData()
|
||||
{
|
||||
@@ -17,7 +18,6 @@ void VertexData::resetMeshData()
|
||||
{
|
||||
mat.material->getDescriptorLayout()->reset();
|
||||
}
|
||||
materialData.clear();
|
||||
if (dirty)
|
||||
{
|
||||
updateBuffers();
|
||||
@@ -25,7 +25,7 @@ void VertexData::resetMeshData()
|
||||
}
|
||||
}
|
||||
|
||||
void VertexData::updateMesh(const Component::Transform& transform, PMesh mesh)
|
||||
void VertexData::addMesh(PMesh mesh)
|
||||
{
|
||||
PMaterial mat = mesh->referencedMaterial->getHandle()->getBaseMaterial();
|
||||
MaterialData& matData = materialData[mat->getName()];
|
||||
@@ -34,15 +34,66 @@ void VertexData::updateMesh(const Component::Transform& transform, PMesh mesh)
|
||||
matInstanceData.meshes.add(MeshInstanceData{
|
||||
.id = mesh->id,
|
||||
.instance = InstanceData {
|
||||
.transformMatrix = transform.toMatrix(),
|
||||
.transformMatrix = Matrix4(),
|
||||
},
|
||||
.indexBuffer = mesh->indexBuffer,
|
||||
});
|
||||
matInstanceData.materialInstance = mesh->referencedMaterial->getHandle();
|
||||
matInstanceData.materialInstance->updateDescriptor();
|
||||
matInstanceData.numMeshes += meshData[mesh->id].size();
|
||||
}
|
||||
|
||||
void VertexData::removeMesh(PMesh mesh)
|
||||
{
|
||||
PMaterial mat = mesh->referencedMaterial->getHandle()->getBaseMaterial();
|
||||
MaterialData& matData = materialData[mat->getName()];
|
||||
matData.material = mat;
|
||||
MaterialInstanceData& matInstanceData = matData.instances[mesh->referencedMaterial->getHandle()->getId()];
|
||||
matInstanceData.meshes.remove_if([&mesh](const MeshInstanceData& data) {
|
||||
return data.id == mesh->id;
|
||||
});
|
||||
matInstanceData.materialInstance = mesh->referencedMaterial->getHandle();
|
||||
matInstanceData.numMeshes -= meshData[mesh->id].size();
|
||||
}
|
||||
|
||||
void VertexData::updateInstances()
|
||||
{
|
||||
instanceDataLayout->reset();
|
||||
for (const auto& [_, mat] : materialData)
|
||||
{
|
||||
for (auto& [_, matInst] : mat.instances)
|
||||
{
|
||||
Array<InstanceData> instanceData;
|
||||
for (auto& inst : matInst.meshes)
|
||||
{
|
||||
inst.meshes = 0;
|
||||
for (const auto& mesh : meshData[inst.id])
|
||||
{
|
||||
instanceData.add(inst.instance);
|
||||
inst.meshes++;
|
||||
}
|
||||
}
|
||||
matInst.instanceBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
||||
.sourceData = {
|
||||
.size = sizeof(InstanceData) * instanceData.size(),
|
||||
.data = (uint8*)instanceData.data(),
|
||||
},
|
||||
.numElements = instanceData.size(),
|
||||
.dynamic = false,
|
||||
});
|
||||
matInst.descriptorSet = instanceDataLayout->allocateDescriptorSet();
|
||||
matInst.descriptorSet->updateBuffer(0, matInst.instanceBuffer);
|
||||
if (graphics->supportMeshShading())
|
||||
{
|
||||
matInst.descriptorSet->updateBuffer(1, matInst.meshDataBuffer);
|
||||
matInst.descriptorSet->updateBuffer(2, meshletBuffer);
|
||||
matInst.descriptorSet->updateBuffer(3, primitiveIndicesBuffer);
|
||||
matInst.descriptorSet->updateBuffer(4, vertexIndicesBuffer);
|
||||
}
|
||||
matInst.descriptorSet->writeChanges();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VertexData::createDescriptors()
|
||||
{
|
||||
instanceDataLayout->reset();
|
||||
@@ -50,14 +101,12 @@ void VertexData::createDescriptors()
|
||||
{
|
||||
for (auto& [_, matInst] : mat.instances)
|
||||
{
|
||||
Array<InstanceData> instanceData;
|
||||
Array<MeshData> meshes;
|
||||
for (auto& inst : matInst.meshes)
|
||||
{
|
||||
inst.meshes = 0;
|
||||
for (const auto& mesh : meshData[inst.id])
|
||||
{
|
||||
instanceData.add(inst.instance);
|
||||
meshes.add(mesh);
|
||||
inst.meshes++;
|
||||
}
|
||||
@@ -95,6 +144,9 @@ void VertexData::createDescriptors()
|
||||
|
||||
void VertexData::loadMesh(MeshId id, Array<Meshlet> loadedMeshlets)
|
||||
{
|
||||
meshlets.reserve(meshlets.size() + loadedMeshlets.size());
|
||||
vertexIndices.reserve(vertexIndices.size() + loadedMeshlets.size() * Gfx::numVerticesPerMeshlet);
|
||||
vertexIndices.reserve(vertexIndices.size() + loadedMeshlets.size() * Gfx::numPrimitivesPerMeshlet * 3);
|
||||
meshData[id].clear();
|
||||
uint32 currentMesh = 0;
|
||||
while (currentMesh < loadedMeshlets.size())
|
||||
@@ -239,3 +291,69 @@ void Meshlet::load(ArchiveBuffer& buffer)
|
||||
Serialization::load(buffer, numVertices);
|
||||
Serialization::load(buffer, numPrimitives);
|
||||
}
|
||||
|
||||
void Seele::Meshlet::buildFromIndexBuffer(const Array<uint32>& indices, Array<Meshlet>& meshlets)
|
||||
{
|
||||
std::set<uint32> uniqueVertices;
|
||||
Meshlet current = {
|
||||
.numVertices = 0,
|
||||
.numPrimitives = 0,
|
||||
};
|
||||
auto insertAndGetIndex = [&uniqueVertices, ¤t](uint32 index) -> int8_t
|
||||
{
|
||||
auto [it, inserted] = uniqueVertices.insert(index);
|
||||
if (inserted)
|
||||
{
|
||||
if (current.numVertices == Gfx::numVerticesPerMeshlet)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
current.uniqueVertices[current.numVertices] = index;
|
||||
return current.numVertices++;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (uint32 i = 0; i < current.numVertices; ++i)
|
||||
{
|
||||
if (current.uniqueVertices[i] == index)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
assert(false);
|
||||
}
|
||||
};
|
||||
auto completeMeshlet = [&meshlets, ¤t, &uniqueVertices]() {
|
||||
meshlets.add(current);
|
||||
current = {
|
||||
.numVertices = 0,
|
||||
.numPrimitives = 0,
|
||||
};
|
||||
uniqueVertices.clear();
|
||||
};
|
||||
for (size_t faceIndex = 0; faceIndex < indices.size() / 3; ++faceIndex)
|
||||
{
|
||||
auto i1 = insertAndGetIndex(indices[faceIndex * 3 + 0]);
|
||||
auto i2 = insertAndGetIndex(indices[faceIndex * 3 + 1]);
|
||||
auto i3 = insertAndGetIndex(indices[faceIndex * 3 + 2]);
|
||||
if (i1 == -1 || i2 == -1 || i3 == -1)
|
||||
{
|
||||
completeMeshlet();
|
||||
i1 = insertAndGetIndex(indices[faceIndex * 3 + 0]);
|
||||
i2 = insertAndGetIndex(indices[faceIndex * 3 + 1]);
|
||||
i3 = insertAndGetIndex(indices[faceIndex * 3 + 2]);
|
||||
}
|
||||
current.primitiveLayout[current.numPrimitives * 3 + 0] = i1;
|
||||
current.primitiveLayout[current.numPrimitives * 3 + 1] = i2;
|
||||
current.primitiveLayout[current.numPrimitives * 3 + 2] = i3;
|
||||
current.numPrimitives++;
|
||||
if (current.numPrimitives == Gfx::numPrimitivesPerMeshlet)
|
||||
{
|
||||
completeMeshlet();
|
||||
}
|
||||
}
|
||||
if (!uniqueVertices.empty())
|
||||
{
|
||||
completeMeshlet();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,10 @@ struct MeshId
|
||||
{
|
||||
return id <=> other.id;
|
||||
}
|
||||
bool operator==(const MeshId& other) const
|
||||
{
|
||||
return id == other.id;
|
||||
}
|
||||
};
|
||||
struct Meshlet
|
||||
{
|
||||
@@ -26,6 +30,7 @@ struct Meshlet
|
||||
uint32 numPrimitives;
|
||||
void save(ArchiveBuffer& buffer) const;
|
||||
void load(ArchiveBuffer& buffer);
|
||||
static void buildFromIndexBuffer(const Array<uint32>& indices, Array<Meshlet>& meshlets);
|
||||
};
|
||||
class VertexData
|
||||
{
|
||||
@@ -47,7 +52,7 @@ public:
|
||||
Gfx::OShaderBuffer instanceBuffer;
|
||||
Gfx::OShaderBuffer meshDataBuffer;
|
||||
Gfx::PDescriptorSet descriptorSet;
|
||||
uint32 numMeshes; // not necessarily equal to meshes.size() if a MeshId has multiple meshes
|
||||
uint32 numMeshes = 0; // not necessarily equal to meshes.size() if a MeshId has multiple meshes
|
||||
Array<MeshInstanceData> meshes;
|
||||
};
|
||||
struct MaterialData
|
||||
@@ -62,7 +67,9 @@ public:
|
||||
uint32 indicesOffset;
|
||||
};
|
||||
void resetMeshData();
|
||||
void updateMesh(const Component::Transform& transform, PMesh mesh);
|
||||
void addMesh(PMesh mesh);
|
||||
void removeMesh(PMesh mesh);
|
||||
void updateInstances();
|
||||
void createDescriptors();
|
||||
void loadMesh(MeshId id, Array<Meshlet> meshlets);
|
||||
MeshId allocateVertexData(uint64 numVertices);
|
||||
|
||||
@@ -327,7 +327,7 @@ OStagingBuffer StagingManager::create(uint64 size)
|
||||
.pNext = nullptr,
|
||||
.flags = 0,
|
||||
.size = size,
|
||||
.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
|
||||
.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
|
||||
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
|
||||
.queueFamilyIndexCount = 1,
|
||||
.pQueueFamilyIndices = &queueIndex,
|
||||
|
||||
@@ -359,11 +359,15 @@ void Graphics::pickPhysicalDevice()
|
||||
vkEnumeratePhysicalDevices(instance, &physicalDeviceCount, physicalDevices.data());
|
||||
VkPhysicalDevice bestDevice = VK_NULL_HANDLE;
|
||||
uint32 deviceRating = 0;
|
||||
features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
|
||||
features.pNext = &features12;
|
||||
features12.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES;
|
||||
features12.pNext = nullptr;
|
||||
for (auto dev : physicalDevices)
|
||||
{
|
||||
uint32 currentRating = 0;
|
||||
vkGetPhysicalDeviceProperties(dev, &props);
|
||||
vkGetPhysicalDeviceFeatures(dev, &features);
|
||||
vkGetPhysicalDeviceFeatures2(dev, &features);
|
||||
if (props.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU)
|
||||
{
|
||||
std::cout << "found dedicated gpu " << props.deviceName << std::endl;
|
||||
@@ -382,8 +386,9 @@ void Graphics::pickPhysicalDevice()
|
||||
}
|
||||
}
|
||||
physicalDevice = bestDevice;
|
||||
|
||||
vkGetPhysicalDeviceProperties(physicalDevice, &props);
|
||||
vkGetPhysicalDeviceFeatures(physicalDevice, &features);
|
||||
vkGetPhysicalDeviceFeatures2(physicalDevice, &features);
|
||||
if (Gfx::useMeshShading)
|
||||
{
|
||||
uint32 count = 0;
|
||||
@@ -500,31 +505,25 @@ void Graphics::createDevice(GraphicsInitializer initializer)
|
||||
*currentPriority++ = 1.0f;
|
||||
}
|
||||
}
|
||||
VkPhysicalDeviceDescriptorIndexingFeatures descriptorIndexing = {
|
||||
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES,
|
||||
.shaderSampledImageArrayNonUniformIndexing = VK_TRUE,
|
||||
.descriptorBindingPartiallyBound = VK_TRUE,
|
||||
.descriptorBindingVariableDescriptorCount = VK_TRUE,
|
||||
.runtimeDescriptorArray = VK_TRUE,
|
||||
};
|
||||
VkPhysicalDeviceMeshShaderFeaturesEXT enabledMeshShaderFeatures = {
|
||||
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_FEATURES_EXT,
|
||||
.pNext = nullptr,
|
||||
.taskShader = VK_TRUE,
|
||||
.meshShader = VK_TRUE,
|
||||
};
|
||||
if (supportMeshShading())
|
||||
{
|
||||
descriptorIndexing.pNext = &enabledMeshShaderFeatures;
|
||||
features12.pNext = &enabledMeshShaderFeatures;
|
||||
initializer.deviceExtensions.add(VK_EXT_MESH_SHADER_EXTENSION_NAME);
|
||||
}
|
||||
VkDeviceCreateInfo deviceInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
|
||||
.pNext = &descriptorIndexing,
|
||||
.pNext = &features12,
|
||||
.queueCreateInfoCount = (uint32)queueInfos.size(),
|
||||
.pQueueCreateInfos = queueInfos.data(),
|
||||
.enabledExtensionCount = (uint32)initializer.deviceExtensions.size(),
|
||||
.ppEnabledExtensionNames = initializer.deviceExtensions.data(),
|
||||
.pEnabledFeatures = &features,
|
||||
.pEnabledFeatures = &features.features,
|
||||
};
|
||||
|
||||
VK_CHECK(vkCreateDevice(physicalDevice, &deviceInfo, nullptr, &handle));
|
||||
|
||||
@@ -91,7 +91,8 @@ protected:
|
||||
thread_local static OCommandPool transferCommands;
|
||||
thread_local static OCommandPool dedicatedTransferCommands;
|
||||
VkPhysicalDeviceProperties props;
|
||||
VkPhysicalDeviceFeatures features;
|
||||
VkPhysicalDeviceFeatures2 features;
|
||||
VkPhysicalDeviceVulkan12Features features12;
|
||||
VkDebugReportCallbackEXT callback;
|
||||
Map<uint32, OFramebuffer> allocatedFramebuffers;
|
||||
OAllocator allocator;
|
||||
|
||||
@@ -358,7 +358,6 @@ PGraphicsPipeline PipelineCache::createPipeline(Gfx::MeshPipelineCreateInfo gfxI
|
||||
|
||||
if (graphicsPipelines.contains(hash))
|
||||
{
|
||||
std::cout << "Caching pipeline" << std::endl;
|
||||
return graphicsPipelines[hash];
|
||||
}
|
||||
VkPipeline pipelineHandle;
|
||||
|
||||
@@ -257,14 +257,14 @@ void Window::chooseSwapSurfaceFormat()
|
||||
|
||||
void Window::chooseSwapPresentMode()
|
||||
{
|
||||
for (const auto& supportedPresentMode : supportedPresentModes)
|
||||
/*for (const auto& supportedPresentMode : supportedPresentModes)
|
||||
{
|
||||
if (supportedPresentMode == VK_PRESENT_MODE_MAILBOX_KHR)
|
||||
{
|
||||
presentMode = supportedPresentMode;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
presentMode = VK_PRESENT_MODE_FIFO_KHR;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user