Create VkLevelMeshUploader
This commit is contained in:
parent
ed7da1ae25
commit
486a08e882
8 changed files with 425 additions and 329 deletions
|
|
@ -81,14 +81,14 @@ LevelSubmesh::LevelSubmesh()
|
|||
Mesh.Vertices.Push({ maxval, maxval, maxval });
|
||||
|
||||
for (int i = 0; i < 3 * 4; i++)
|
||||
Mesh.Elements.Push(i);
|
||||
Mesh.Indexes.Push(i);
|
||||
|
||||
UpdateCollision();
|
||||
}
|
||||
|
||||
void LevelSubmesh::UpdateCollision()
|
||||
{
|
||||
Collision = std::make_unique<TriangleMeshShape>(Mesh.Vertices.Data(), Mesh.Vertices.Size(), Mesh.Elements.Data(), Mesh.Elements.Size());
|
||||
Collision = std::make_unique<TriangleMeshShape>(Mesh.Vertices.Data(), Mesh.Vertices.Size(), Mesh.Indexes.Data(), Mesh.Indexes.Size());
|
||||
}
|
||||
|
||||
void LevelSubmesh::GatherSurfacePixelStats(LevelMeshSurfaceStats& stats)
|
||||
|
|
|
|||
|
|
@ -259,7 +259,7 @@ public:
|
|||
struct
|
||||
{
|
||||
TArray<FFlatVertex> Vertices;
|
||||
TArray<uint32_t> Elements;
|
||||
TArray<uint32_t> Indexes;
|
||||
TArray<int> SurfaceIndexes;
|
||||
TArray<int> UniformIndexes;
|
||||
TArray<SurfaceUniforms> Uniforms;
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ void VkDescriptorSetManager::UpdateLevelMeshSet()
|
|||
WriteDescriptors()
|
||||
.AddBuffer(LevelMesh.Set.get(), 0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, rsbuffers->Viewpoint.UBO.get(), 0, sizeof(HWViewpointUniforms))
|
||||
.AddBuffer(LevelMesh.Set.get(), 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, rsbuffers->MatrixBuffer->UBO(), 0, sizeof(MatricesUBO))
|
||||
.AddBuffer(LevelMesh.Set.get(), 2, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetLevelMesh()->GetSurfaceUniformsBuffer())
|
||||
.AddBuffer(LevelMesh.Set.get(), 2, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetLevelMesh()->GetUniformsBuffer())
|
||||
.AddBuffer(LevelMesh.Set.get(), 3, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, rsbuffers->Lightbuffer.UBO.get(), 0, sizeof(LightBufferUBO))
|
||||
.AddBuffer(LevelMesh.Set.get(), 4, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, rsbuffers->Bonebuffer.SSO.get())
|
||||
.Execute(fb->GetDevice());
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ void VkLevelMesh::Reset()
|
|||
deletelist->Add(std::move(IndexBuffer));
|
||||
deletelist->Add(std::move(NodeBuffer));
|
||||
deletelist->Add(std::move(SurfaceBuffer));
|
||||
deletelist->Add(std::move(SurfaceUniformsBuffer));
|
||||
deletelist->Add(std::move(UniformsBuffer));
|
||||
deletelist->Add(std::move(SurfaceIndexBuffer));
|
||||
deletelist->Add(std::move(PortalBuffer));
|
||||
deletelist->Add(std::move(StaticBLAS.ScratchBuffer));
|
||||
|
|
@ -93,289 +93,8 @@ void VkLevelMesh::BeginFrame()
|
|||
|
||||
void VkLevelMesh::UploadMeshes(bool dynamicOnly)
|
||||
{
|
||||
TArray<SubmeshBufferLocation> locations(2);
|
||||
|
||||
// Find submesh buffer sizes
|
||||
for (LevelSubmesh* submesh : { Mesh->StaticMesh.get(), Mesh->DynamicMesh.get() })
|
||||
{
|
||||
SubmeshBufferLocation location;
|
||||
location.Submesh = submesh;
|
||||
location.VertexSize = submesh->Mesh.Vertices.Size();
|
||||
location.IndexSize = submesh->Mesh.Elements.Size();
|
||||
location.NodeSize = (int)submesh->Collision->get_nodes().size();
|
||||
location.SurfaceIndexSize = submesh->Mesh.SurfaceIndexes.Size();
|
||||
location.SurfaceSize = submesh->GetSurfaceCount();
|
||||
location.UniformsSize = submesh->Mesh.Uniforms.Size();
|
||||
locations.Push(location);
|
||||
}
|
||||
|
||||
// Find submesh locations in buffers
|
||||
for (unsigned int i = 1, count = locations.Size(); i < count; i++)
|
||||
{
|
||||
const SubmeshBufferLocation& prev = locations[i - 1];
|
||||
SubmeshBufferLocation& cur = locations[i];
|
||||
cur.VertexOffset = prev.VertexOffset + prev.VertexSize;
|
||||
cur.IndexOffset = prev.IndexOffset + prev.IndexSize;
|
||||
cur.NodeOffset = prev.NodeOffset + prev.NodeSize;
|
||||
cur.SurfaceIndexOffset = prev.SurfaceIndexOffset + prev.SurfaceIndexSize;
|
||||
cur.SurfaceOffset = prev.SurfaceOffset + prev.SurfaceSize;
|
||||
cur.UniformsOffset = prev.UniformsOffset + prev.UniformsSize;
|
||||
|
||||
if (
|
||||
cur.VertexOffset + cur.VertexSize > GetMaxVertexBufferSize() ||
|
||||
cur.IndexOffset + cur.IndexSize > GetMaxIndexBufferSize() ||
|
||||
cur.NodeOffset + cur.NodeSize > GetMaxNodeBufferSize() ||
|
||||
cur.SurfaceOffset + cur.SurfaceSize > GetMaxSurfaceBufferSize() ||
|
||||
cur.UniformsOffset + cur.UniformsSize > GetMaxUniformsBufferSize() ||
|
||||
cur.SurfaceIndexOffset + cur.SurfaceIndexSize > GetMaxSurfaceIndexBufferSize())
|
||||
{
|
||||
I_FatalError("Dynamic accel struct buffers are too small!");
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int start = dynamicOnly;
|
||||
unsigned int end = locations.Size();
|
||||
|
||||
// Figure out how much memory we need to transfer it to the GPU
|
||||
size_t transferBufferSize = sizeof(CollisionNodeBufferHeader) + sizeof(CollisionNode);
|
||||
for (unsigned int i = start; i < end; i++)
|
||||
{
|
||||
const SubmeshBufferLocation& cur = locations[i];
|
||||
transferBufferSize += cur.Submesh->Mesh.Vertices.Size() * sizeof(FFlatVertex);
|
||||
transferBufferSize += cur.Submesh->Mesh.UniformIndexes.Size() * sizeof(int);
|
||||
transferBufferSize += cur.Submesh->Mesh.Elements.Size() * sizeof(uint32_t);
|
||||
transferBufferSize += cur.Submesh->Collision->get_nodes().size() * sizeof(CollisionNode);
|
||||
transferBufferSize += cur.Submesh->Mesh.SurfaceIndexes.Size() * sizeof(int);
|
||||
transferBufferSize += cur.Submesh->GetSurfaceCount() * sizeof(SurfaceInfo);
|
||||
transferBufferSize += cur.Submesh->Mesh.Uniforms.Size() * sizeof(SurfaceUniforms);
|
||||
}
|
||||
if (!dynamicOnly)
|
||||
transferBufferSize += Mesh->StaticMesh->Portals.Size() * sizeof(PortalInfo);
|
||||
|
||||
// Begin the transfer
|
||||
auto cmdbuffer = fb->GetCommands()->GetTransferCommands();
|
||||
auto transferBuffer = BufferBuilder()
|
||||
.Usage(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY)
|
||||
.Size(transferBufferSize)
|
||||
.DebugName("UploadMeshes")
|
||||
.Create(fb->GetDevice());
|
||||
|
||||
uint8_t* data = (uint8_t*)transferBuffer->Map(0, transferBufferSize);
|
||||
size_t datapos = 0;
|
||||
|
||||
// Copy node buffer header and create a root node that merges the static and dynamic AABB trees
|
||||
if (locations[1].Submesh->Collision->get_root() != -1)
|
||||
{
|
||||
int root0 = locations[0].Submesh->Collision->get_root();
|
||||
int root1 = locations[1].Submesh->Collision->get_root();
|
||||
const auto& node0 = locations[0].Submesh->Collision->get_nodes()[root0];
|
||||
const auto& node1 = locations[1].Submesh->Collision->get_nodes()[root1];
|
||||
|
||||
FVector3 aabbMin(std::min(node0.aabb.min.X, node1.aabb.min.X), std::min(node0.aabb.min.Y, node1.aabb.min.Y), std::min(node0.aabb.min.Z, node1.aabb.min.Z));
|
||||
FVector3 aabbMax(std::max(node0.aabb.max.X, node1.aabb.max.X), std::max(node0.aabb.max.Y, node1.aabb.max.Y), std::max(node0.aabb.max.Z, node1.aabb.max.Z));
|
||||
CollisionBBox bbox(aabbMin, aabbMax);
|
||||
|
||||
CollisionNodeBufferHeader nodesHeader;
|
||||
nodesHeader.root = locations[1].NodeOffset + locations[1].NodeSize;
|
||||
|
||||
CollisionNode info;
|
||||
info.center = bbox.Center;
|
||||
info.extents = bbox.Extents;
|
||||
info.left = locations[0].NodeOffset + root0;
|
||||
info.right = locations[1].NodeOffset + root1;
|
||||
info.element_index = -1;
|
||||
|
||||
*((CollisionNodeBufferHeader*)(data + datapos)) = nodesHeader;
|
||||
*((CollisionNode*)(data + datapos + sizeof(CollisionNodeBufferHeader))) = info;
|
||||
|
||||
cmdbuffer->copyBuffer(transferBuffer.get(), NodeBuffer.get(), datapos, 0, sizeof(CollisionNodeBufferHeader));
|
||||
cmdbuffer->copyBuffer(transferBuffer.get(), NodeBuffer.get(), datapos + sizeof(CollisionNodeBufferHeader), sizeof(CollisionNodeBufferHeader) + nodesHeader.root * sizeof(CollisionNode), sizeof(CollisionNode));
|
||||
}
|
||||
else // second submesh is empty, just point the header at the first one
|
||||
{
|
||||
CollisionNodeBufferHeader nodesHeader;
|
||||
nodesHeader.root = locations[0].Submesh->Collision->get_root();
|
||||
|
||||
*((CollisionNodeBufferHeader*)(data + datapos)) = nodesHeader;
|
||||
cmdbuffer->copyBuffer(transferBuffer.get(), NodeBuffer.get(), datapos, 0, sizeof(CollisionNodeBufferHeader));
|
||||
}
|
||||
datapos += sizeof(CollisionNodeBufferHeader) + sizeof(CollisionNode);
|
||||
|
||||
// Copy vertices
|
||||
for (unsigned int i = start; i < end; i++)
|
||||
{
|
||||
const SubmeshBufferLocation& cur = locations[i];
|
||||
auto submesh = cur.Submesh;
|
||||
|
||||
size_t copysize = submesh->Mesh.Vertices.Size() * sizeof(FFlatVertex);
|
||||
memcpy(data + datapos, submesh->Mesh.Vertices.Data(), copysize);
|
||||
if (copysize > 0)
|
||||
cmdbuffer->copyBuffer(transferBuffer.get(), VertexBuffer.get(), datapos, cur.VertexOffset * sizeof(FFlatVertex), copysize);
|
||||
datapos += copysize;
|
||||
}
|
||||
|
||||
// Copy uniform indexes
|
||||
for (unsigned int i = start; i < end; i++)
|
||||
{
|
||||
const SubmeshBufferLocation& cur = locations[i];
|
||||
auto submesh = cur.Submesh;
|
||||
|
||||
size_t copysize = submesh->Mesh.UniformIndexes.Size() * sizeof(int);
|
||||
memcpy(data + datapos, submesh->Mesh.UniformIndexes.Data(), copysize);
|
||||
if (copysize > 0)
|
||||
cmdbuffer->copyBuffer(transferBuffer.get(), UniformIndexBuffer.get(), datapos, cur.VertexOffset * sizeof(int), copysize);
|
||||
datapos += copysize;
|
||||
}
|
||||
|
||||
// Copy indexes
|
||||
for (unsigned int i = start; i < end; i++)
|
||||
{
|
||||
const SubmeshBufferLocation& cur = locations[i];
|
||||
auto submesh = cur.Submesh;
|
||||
|
||||
uint32_t* indexes = (uint32_t*)(data + datapos);
|
||||
for (int j = 0, count = submesh->Mesh.Elements.Size(); j < count; ++j)
|
||||
*(indexes++) = cur.VertexOffset + submesh->Mesh.Elements[j];
|
||||
|
||||
size_t copysize = submesh->Mesh.Elements.Size() * sizeof(uint32_t);
|
||||
if (copysize > 0)
|
||||
cmdbuffer->copyBuffer(transferBuffer.get(), IndexBuffer.get(), datapos, cur.IndexOffset * sizeof(uint32_t), copysize);
|
||||
datapos += copysize;
|
||||
}
|
||||
|
||||
// Copy collision nodes
|
||||
for (unsigned int i = start; i < end; i++)
|
||||
{
|
||||
const SubmeshBufferLocation& cur = locations[i];
|
||||
auto submesh = cur.Submesh;
|
||||
|
||||
CollisionNode* nodes = (CollisionNode*)(data + datapos);
|
||||
for (auto& node : submesh->Collision->get_nodes())
|
||||
{
|
||||
CollisionNode info;
|
||||
info.center = node.aabb.Center;
|
||||
info.extents = node.aabb.Extents;
|
||||
info.left = node.left != -1 ? node.left + cur.NodeOffset : -1;
|
||||
info.right = node.right != -1 ? node.right + cur.NodeOffset : -1;
|
||||
info.element_index = node.element_index != -1 ? node.element_index + cur.IndexOffset : -1;
|
||||
*(nodes++) = info;
|
||||
}
|
||||
|
||||
size_t copysize = submesh->Collision->get_nodes().size() * sizeof(CollisionNode);
|
||||
if (copysize > 0)
|
||||
cmdbuffer->copyBuffer(transferBuffer.get(), NodeBuffer.get(), datapos, +sizeof(CollisionNodeBufferHeader) + cur.NodeOffset * sizeof(CollisionNode), copysize);
|
||||
datapos += copysize;
|
||||
}
|
||||
|
||||
// Copy surface indexes
|
||||
for (unsigned int i = start; i < end; i++)
|
||||
{
|
||||
const SubmeshBufferLocation& cur = locations[i];
|
||||
auto submesh = cur.Submesh;
|
||||
|
||||
int* indexes = (int*)(data + datapos);
|
||||
for (int j = 0, count = submesh->Mesh.SurfaceIndexes.Size(); j < count; ++j)
|
||||
*(indexes++) = cur.SurfaceIndexOffset + submesh->Mesh.SurfaceIndexes[j];
|
||||
|
||||
size_t copysize = submesh->Mesh.SurfaceIndexes.Size() * sizeof(int);
|
||||
if (copysize > 0)
|
||||
cmdbuffer->copyBuffer(transferBuffer.get(), SurfaceIndexBuffer.get(), datapos, cur.SurfaceIndexOffset * sizeof(int), copysize);
|
||||
datapos += copysize;
|
||||
}
|
||||
|
||||
// Copy surfaces
|
||||
for (unsigned int i = start; i < end; i++)
|
||||
{
|
||||
const SubmeshBufferLocation& cur = locations[i];
|
||||
auto submesh = cur.Submesh;
|
||||
|
||||
SurfaceInfo* surfaces = (SurfaceInfo*)(data + datapos);
|
||||
for (int j = 0, count = submesh->GetSurfaceCount(); j < count; ++j)
|
||||
{
|
||||
LevelMeshSurface* surface = submesh->GetSurface(j);
|
||||
|
||||
SurfaceInfo info;
|
||||
info.Normal = FVector3(surface->plane.X, surface->plane.Z, surface->plane.Y);
|
||||
info.PortalIndex = surface->portalIndex;
|
||||
info.SamplingDistance = (float)surface->sampleDimension;
|
||||
info.Sky = surface->bSky;
|
||||
info.Alpha = surface->alpha;
|
||||
if (surface->texture)
|
||||
{
|
||||
auto mat = FMaterial::ValidateTexture(surface->texture, 0);
|
||||
info.TextureIndex = fb->GetBindlessTextureIndex(mat, CLAMP_NONE, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
info.TextureIndex = 0;
|
||||
}
|
||||
|
||||
*(surfaces++) = info;
|
||||
}
|
||||
|
||||
size_t copysize = submesh->GetSurfaceCount() * sizeof(SurfaceInfo);
|
||||
if (copysize > 0)
|
||||
cmdbuffer->copyBuffer(transferBuffer.get(), SurfaceBuffer.get(), datapos, cur.SurfaceOffset * sizeof(SurfaceInfo), copysize);
|
||||
datapos += copysize;
|
||||
}
|
||||
|
||||
// Copy surface uniforms
|
||||
for (unsigned int i = start; i < end; i++)
|
||||
{
|
||||
const SubmeshBufferLocation& cur = locations[i];
|
||||
auto submesh = cur.Submesh;
|
||||
|
||||
for (int j = 0, count = submesh->Mesh.Uniforms.Size(); j < count; j++)
|
||||
{
|
||||
auto& surfaceUniforms = submesh->Mesh.Uniforms[j];
|
||||
auto& material = submesh->Mesh.Materials[j];
|
||||
if (material.mMaterial)
|
||||
{
|
||||
auto source = material.mMaterial->Source();
|
||||
surfaceUniforms.uSpecularMaterial = { source->GetGlossiness(), source->GetSpecularLevel() };
|
||||
surfaceUniforms.uTextureIndex = fb->GetBindlessTextureIndex(material.mMaterial, material.mClampMode, material.mTranslation);
|
||||
}
|
||||
else
|
||||
{
|
||||
surfaceUniforms.uTextureIndex = 0;
|
||||
}
|
||||
}
|
||||
|
||||
SurfaceUniforms* uniforms = (SurfaceUniforms*)(data + datapos);
|
||||
size_t copysize = submesh->Mesh.Uniforms.Size() * sizeof(SurfaceUniforms);
|
||||
memcpy(uniforms, submesh->Mesh.Uniforms.Data(), copysize);
|
||||
if (copysize > 0)
|
||||
cmdbuffer->copyBuffer(transferBuffer.get(), SurfaceUniformsBuffer.get(), datapos, cur.UniformsOffset * sizeof(SurfaceUniforms), copysize);
|
||||
datapos += copysize;
|
||||
}
|
||||
|
||||
// Copy portals
|
||||
if (!dynamicOnly)
|
||||
{
|
||||
PortalInfo* portals = (PortalInfo*)(data + datapos);
|
||||
for (auto& portal : Mesh->StaticMesh->Portals)
|
||||
{
|
||||
PortalInfo info;
|
||||
info.transformation = portal.transformation;
|
||||
*(portals++) = info;
|
||||
}
|
||||
|
||||
size_t copysize = Mesh->StaticMesh->Portals.Size() * sizeof(PortalInfo);
|
||||
if (copysize > 0)
|
||||
cmdbuffer->copyBuffer(transferBuffer.get(), PortalBuffer.get(), datapos, 0, copysize);
|
||||
datapos += copysize;
|
||||
}
|
||||
|
||||
assert(datapos == transferBufferSize);
|
||||
|
||||
// End the transfer
|
||||
transferBuffer->Unmap();
|
||||
|
||||
fb->GetCommands()->TransferDeleteList->Add(std::move(transferBuffer));
|
||||
|
||||
PipelineBarrier()
|
||||
.AddMemory(VK_ACCESS_TRANSFER_WRITE_BIT, useRayQuery ? VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR : VK_ACCESS_SHADER_READ_BIT)
|
||||
.Execute(fb->GetCommands()->GetTransferCommands(), VK_PIPELINE_STAGE_TRANSFER_BIT, useRayQuery ? VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR : VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
|
||||
VkLevelMeshUploader uploader(this);
|
||||
uploader.Upload(dynamicOnly);
|
||||
}
|
||||
|
||||
int VkLevelMesh::GetMaxVertexBufferSize()
|
||||
|
|
@ -385,7 +104,7 @@ int VkLevelMesh::GetMaxVertexBufferSize()
|
|||
|
||||
int VkLevelMesh::GetMaxIndexBufferSize()
|
||||
{
|
||||
return Mesh->StaticMesh->Mesh.Elements.Size() + MaxDynamicIndexes;
|
||||
return Mesh->StaticMesh->Mesh.Indexes.Size() + MaxDynamicIndexes;
|
||||
}
|
||||
|
||||
int VkLevelMesh::GetMaxNodeBufferSize()
|
||||
|
|
@ -460,7 +179,7 @@ void VkLevelMesh::CreateBuffers()
|
|||
.DebugName("SurfaceBuffer")
|
||||
.Create(fb->GetDevice());
|
||||
|
||||
SurfaceUniformsBuffer = BufferBuilder()
|
||||
UniformsBuffer = BufferBuilder()
|
||||
.Usage(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT)
|
||||
.Size(GetMaxUniformsBufferSize() * sizeof(SurfaceUniforms))
|
||||
.DebugName("SurfaceUniformsBuffer")
|
||||
|
|
@ -497,7 +216,7 @@ VkLevelMesh::BLAS VkLevelMesh::CreateBLAS(LevelSubmesh* submesh, bool preferFast
|
|||
buildInfo.geometryCount = 1;
|
||||
buildInfo.ppGeometries = geometries;
|
||||
|
||||
uint32_t maxPrimitiveCount = submesh->Mesh.Elements.Size() / 3;
|
||||
uint32_t maxPrimitiveCount = submesh->Mesh.Indexes.Size() / 3;
|
||||
|
||||
VkAccelerationStructureBuildSizesInfoKHR sizeInfo = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR };
|
||||
vkGetAccelerationStructureBuildSizesKHR(fb->GetDevice()->device, VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, &buildInfo, &maxPrimitiveCount, &sizeInfo);
|
||||
|
|
@ -545,7 +264,7 @@ void VkLevelMesh::CreateStaticBLAS()
|
|||
|
||||
void VkLevelMesh::CreateDynamicBLAS()
|
||||
{
|
||||
DynamicBLAS = CreateBLAS(Mesh->DynamicMesh.get(), true, Mesh->StaticMesh->Mesh.Vertices.Size(), Mesh->StaticMesh->Mesh.Elements.Size());
|
||||
DynamicBLAS = CreateBLAS(Mesh->DynamicMesh.get(), true, Mesh->StaticMesh->Mesh.Vertices.Size(), Mesh->StaticMesh->Mesh.Indexes.Size());
|
||||
}
|
||||
|
||||
void VkLevelMesh::CreateTopLevelAS()
|
||||
|
|
@ -657,7 +376,7 @@ void VkLevelMesh::UpdateDynamicBLAS()
|
|||
deletelist->Add(std::move(DynamicBLAS.AccelStructBuffer));
|
||||
deletelist->Add(std::move(DynamicBLAS.AccelStruct));
|
||||
|
||||
DynamicBLAS = CreateBLAS(Mesh->DynamicMesh.get(), true, Mesh->StaticMesh->Mesh.Vertices.Size(), Mesh->StaticMesh->Mesh.Elements.Size());
|
||||
DynamicBLAS = CreateBLAS(Mesh->DynamicMesh.get(), true, Mesh->StaticMesh->Mesh.Vertices.Size(), Mesh->StaticMesh->Mesh.Indexes.Size());
|
||||
}
|
||||
|
||||
void VkLevelMesh::UpdateTopLevelAS()
|
||||
|
|
@ -717,3 +436,345 @@ void VkLevelMesh::UpdateTopLevelAS()
|
|||
.Execute(fb->GetCommands()->GetTransferCommands(), VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
VkLevelMeshUploader::VkLevelMeshUploader(VkLevelMesh* mesh) : Mesh(mesh)
|
||||
{
|
||||
}
|
||||
|
||||
void VkLevelMeshUploader::Upload(bool dynamicOnly)
|
||||
{
|
||||
UpdateSizes();
|
||||
UpdateLocations();
|
||||
|
||||
start = dynamicOnly;
|
||||
end = locations.Size();
|
||||
|
||||
size_t transferBufferSize = GetTransferSize();
|
||||
if (transferBufferSize == 0)
|
||||
return;
|
||||
|
||||
BeginTransfer(transferBufferSize);
|
||||
|
||||
UploadNodes();
|
||||
UploadVertices();
|
||||
UploadUniformIndexes();
|
||||
UploadIndexes();
|
||||
UploadSurfaceIndexes();
|
||||
UploadSurfaces();
|
||||
UploadUniforms();
|
||||
UploadPortals();
|
||||
|
||||
EndTransfer(transferBufferSize);
|
||||
}
|
||||
|
||||
void VkLevelMeshUploader::BeginTransfer(size_t transferBufferSize)
|
||||
{
|
||||
cmdbuffer = Mesh->fb->GetCommands()->GetTransferCommands();
|
||||
transferBuffer = BufferBuilder()
|
||||
.Usage(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY)
|
||||
.Size(transferBufferSize)
|
||||
.DebugName("UploadMeshes")
|
||||
.Create(Mesh->fb->GetDevice());
|
||||
|
||||
data = (uint8_t*)transferBuffer->Map(0, transferBufferSize);
|
||||
datapos = 0;
|
||||
}
|
||||
|
||||
void VkLevelMeshUploader::EndTransfer(size_t transferBufferSize)
|
||||
{
|
||||
assert(datapos == transferBufferSize);
|
||||
|
||||
transferBuffer->Unmap();
|
||||
|
||||
Mesh->fb->GetCommands()->TransferDeleteList->Add(std::move(transferBuffer));
|
||||
|
||||
PipelineBarrier()
|
||||
.AddMemory(VK_ACCESS_TRANSFER_WRITE_BIT, Mesh->useRayQuery ? VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR : VK_ACCESS_SHADER_READ_BIT)
|
||||
.Execute(Mesh->fb->GetCommands()->GetTransferCommands(), VK_PIPELINE_STAGE_TRANSFER_BIT, Mesh->useRayQuery ? VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR : VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
|
||||
}
|
||||
|
||||
void VkLevelMeshUploader::UploadNodes()
|
||||
{
|
||||
// Copy node buffer header and create a root node that merges the static and dynamic AABB trees
|
||||
if (locations[1].Submesh->Collision->get_root() != -1)
|
||||
{
|
||||
int root0 = locations[0].Submesh->Collision->get_root();
|
||||
int root1 = locations[1].Submesh->Collision->get_root();
|
||||
const auto& node0 = locations[0].Submesh->Collision->get_nodes()[root0];
|
||||
const auto& node1 = locations[1].Submesh->Collision->get_nodes()[root1];
|
||||
|
||||
FVector3 aabbMin(std::min(node0.aabb.min.X, node1.aabb.min.X), std::min(node0.aabb.min.Y, node1.aabb.min.Y), std::min(node0.aabb.min.Z, node1.aabb.min.Z));
|
||||
FVector3 aabbMax(std::max(node0.aabb.max.X, node1.aabb.max.X), std::max(node0.aabb.max.Y, node1.aabb.max.Y), std::max(node0.aabb.max.Z, node1.aabb.max.Z));
|
||||
CollisionBBox bbox(aabbMin, aabbMax);
|
||||
|
||||
CollisionNodeBufferHeader nodesHeader;
|
||||
nodesHeader.root = locations[1].Node.Offset + locations[1].Node.Size;
|
||||
|
||||
CollisionNode info;
|
||||
info.center = bbox.Center;
|
||||
info.extents = bbox.Extents;
|
||||
info.left = locations[0].Node.Offset + root0;
|
||||
info.right = locations[1].Node.Offset + root1;
|
||||
info.element_index = -1;
|
||||
|
||||
*((CollisionNodeBufferHeader*)(data + datapos)) = nodesHeader;
|
||||
*((CollisionNode*)(data + datapos + sizeof(CollisionNodeBufferHeader))) = info;
|
||||
|
||||
cmdbuffer->copyBuffer(transferBuffer.get(), Mesh->NodeBuffer.get(), datapos, 0, sizeof(CollisionNodeBufferHeader));
|
||||
cmdbuffer->copyBuffer(transferBuffer.get(), Mesh->NodeBuffer.get(), datapos + sizeof(CollisionNodeBufferHeader), sizeof(CollisionNodeBufferHeader) + nodesHeader.root * sizeof(CollisionNode), sizeof(CollisionNode));
|
||||
}
|
||||
else // second submesh is empty, just point the header at the first one
|
||||
{
|
||||
CollisionNodeBufferHeader nodesHeader;
|
||||
nodesHeader.root = locations[0].Submesh->Collision->get_root();
|
||||
|
||||
*((CollisionNodeBufferHeader*)(data + datapos)) = nodesHeader;
|
||||
cmdbuffer->copyBuffer(transferBuffer.get(), Mesh->NodeBuffer.get(), datapos, 0, sizeof(CollisionNodeBufferHeader));
|
||||
}
|
||||
datapos += sizeof(CollisionNodeBufferHeader) + sizeof(CollisionNode);
|
||||
|
||||
// Copy collision nodes
|
||||
for (unsigned int i = start; i < end; i++)
|
||||
{
|
||||
const SubmeshBufferLocation& cur = locations[i];
|
||||
auto submesh = cur.Submesh;
|
||||
|
||||
CollisionNode* nodes = (CollisionNode*)(data + datapos);
|
||||
for (auto& node : submesh->Collision->get_nodes())
|
||||
{
|
||||
CollisionNode info;
|
||||
info.center = node.aabb.Center;
|
||||
info.extents = node.aabb.Extents;
|
||||
info.left = node.left != -1 ? node.left + cur.Node.Offset : -1;
|
||||
info.right = node.right != -1 ? node.right + cur.Node.Offset : -1;
|
||||
info.element_index = node.element_index != -1 ? node.element_index + cur.Index.Offset : -1;
|
||||
*(nodes++) = info;
|
||||
}
|
||||
|
||||
size_t copysize = submesh->Collision->get_nodes().size() * sizeof(CollisionNode);
|
||||
if (copysize > 0)
|
||||
cmdbuffer->copyBuffer(transferBuffer.get(), Mesh->NodeBuffer.get(), datapos, +sizeof(CollisionNodeBufferHeader) + cur.Node.Offset * sizeof(CollisionNode), copysize);
|
||||
datapos += copysize;
|
||||
}
|
||||
}
|
||||
|
||||
void VkLevelMeshUploader::UploadVertices()
|
||||
{
|
||||
for (unsigned int i = start; i < end; i++)
|
||||
{
|
||||
const SubmeshBufferLocation& cur = locations[i];
|
||||
auto submesh = cur.Submesh;
|
||||
|
||||
size_t copysize = submesh->Mesh.Vertices.Size() * sizeof(FFlatVertex);
|
||||
memcpy(data + datapos, submesh->Mesh.Vertices.Data(), copysize);
|
||||
if (copysize > 0)
|
||||
cmdbuffer->copyBuffer(transferBuffer.get(), Mesh->VertexBuffer.get(), datapos, cur.Vertex.Offset * sizeof(FFlatVertex), copysize);
|
||||
datapos += copysize;
|
||||
}
|
||||
}
|
||||
|
||||
void VkLevelMeshUploader::UploadUniformIndexes()
|
||||
{
|
||||
for (unsigned int i = start; i < end; i++)
|
||||
{
|
||||
const SubmeshBufferLocation& cur = locations[i];
|
||||
auto submesh = cur.Submesh;
|
||||
|
||||
size_t copysize = submesh->Mesh.UniformIndexes.Size() * sizeof(int);
|
||||
memcpy(data + datapos, submesh->Mesh.UniformIndexes.Data(), copysize);
|
||||
if (copysize > 0)
|
||||
cmdbuffer->copyBuffer(transferBuffer.get(), Mesh->UniformIndexBuffer.get(), datapos, cur.UniformIndexes.Offset * sizeof(int), copysize);
|
||||
datapos += copysize;
|
||||
}
|
||||
}
|
||||
|
||||
void VkLevelMeshUploader::UploadIndexes()
|
||||
{
|
||||
for (unsigned int i = start; i < end; i++)
|
||||
{
|
||||
const SubmeshBufferLocation& cur = locations[i];
|
||||
auto submesh = cur.Submesh;
|
||||
|
||||
uint32_t* indexes = (uint32_t*)(data + datapos);
|
||||
for (int j = 0, count = submesh->Mesh.Indexes.Size(); j < count; ++j)
|
||||
*(indexes++) = cur.Vertex.Offset + submesh->Mesh.Indexes[j];
|
||||
|
||||
size_t copysize = submesh->Mesh.Indexes.Size() * sizeof(uint32_t);
|
||||
if (copysize > 0)
|
||||
cmdbuffer->copyBuffer(transferBuffer.get(), Mesh->IndexBuffer.get(), datapos, cur.Index.Offset * sizeof(uint32_t), copysize);
|
||||
datapos += copysize;
|
||||
}
|
||||
}
|
||||
|
||||
void VkLevelMeshUploader::UploadSurfaceIndexes()
|
||||
{
|
||||
for (unsigned int i = start; i < end; i++)
|
||||
{
|
||||
const SubmeshBufferLocation& cur = locations[i];
|
||||
auto submesh = cur.Submesh;
|
||||
|
||||
int* indexes = (int*)(data + datapos);
|
||||
for (int j = 0, count = submesh->Mesh.SurfaceIndexes.Size(); j < count; ++j)
|
||||
*(indexes++) = cur.SurfaceIndex.Offset + submesh->Mesh.SurfaceIndexes[j];
|
||||
|
||||
size_t copysize = submesh->Mesh.SurfaceIndexes.Size() * sizeof(int);
|
||||
if (copysize > 0)
|
||||
cmdbuffer->copyBuffer(transferBuffer.get(), Mesh->SurfaceIndexBuffer.get(), datapos, cur.SurfaceIndex.Offset * sizeof(int), copysize);
|
||||
datapos += copysize;
|
||||
}
|
||||
}
|
||||
|
||||
void VkLevelMeshUploader::UploadSurfaces()
|
||||
{
|
||||
for (unsigned int i = start; i < end; i++)
|
||||
{
|
||||
const SubmeshBufferLocation& cur = locations[i];
|
||||
auto submesh = cur.Submesh;
|
||||
|
||||
SurfaceInfo* surfaces = (SurfaceInfo*)(data + datapos);
|
||||
for (int j = 0, count = submesh->GetSurfaceCount(); j < count; ++j)
|
||||
{
|
||||
LevelMeshSurface* surface = submesh->GetSurface(j);
|
||||
|
||||
SurfaceInfo info;
|
||||
info.Normal = FVector3(surface->plane.X, surface->plane.Z, surface->plane.Y);
|
||||
info.PortalIndex = surface->portalIndex;
|
||||
info.SamplingDistance = (float)surface->sampleDimension;
|
||||
info.Sky = surface->bSky;
|
||||
info.Alpha = surface->alpha;
|
||||
if (surface->texture)
|
||||
{
|
||||
auto mat = FMaterial::ValidateTexture(surface->texture, 0);
|
||||
info.TextureIndex = Mesh->fb->GetBindlessTextureIndex(mat, CLAMP_NONE, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
info.TextureIndex = 0;
|
||||
}
|
||||
|
||||
*(surfaces++) = info;
|
||||
}
|
||||
|
||||
size_t copysize = submesh->GetSurfaceCount() * sizeof(SurfaceInfo);
|
||||
if (copysize > 0)
|
||||
cmdbuffer->copyBuffer(transferBuffer.get(), Mesh->SurfaceBuffer.get(), datapos, cur.Surface.Offset * sizeof(SurfaceInfo), copysize);
|
||||
datapos += copysize;
|
||||
}
|
||||
}
|
||||
|
||||
void VkLevelMeshUploader::UploadUniforms()
|
||||
{
|
||||
for (unsigned int i = start; i < end; i++)
|
||||
{
|
||||
const SubmeshBufferLocation& cur = locations[i];
|
||||
auto submesh = cur.Submesh;
|
||||
|
||||
for (int j = 0, count = submesh->Mesh.Uniforms.Size(); j < count; j++)
|
||||
{
|
||||
auto& surfaceUniforms = submesh->Mesh.Uniforms[j];
|
||||
auto& material = submesh->Mesh.Materials[j];
|
||||
if (material.mMaterial)
|
||||
{
|
||||
auto source = material.mMaterial->Source();
|
||||
surfaceUniforms.uSpecularMaterial = { source->GetGlossiness(), source->GetSpecularLevel() };
|
||||
surfaceUniforms.uTextureIndex = Mesh->fb->GetBindlessTextureIndex(material.mMaterial, material.mClampMode, material.mTranslation);
|
||||
}
|
||||
else
|
||||
{
|
||||
surfaceUniforms.uTextureIndex = 0;
|
||||
}
|
||||
}
|
||||
|
||||
SurfaceUniforms* uniforms = (SurfaceUniforms*)(data + datapos);
|
||||
size_t copysize = submesh->Mesh.Uniforms.Size() * sizeof(SurfaceUniforms);
|
||||
memcpy(uniforms, submesh->Mesh.Uniforms.Data(), copysize);
|
||||
if (copysize > 0)
|
||||
cmdbuffer->copyBuffer(transferBuffer.get(), Mesh->UniformsBuffer.get(), datapos, cur.Uniforms.Offset * sizeof(SurfaceUniforms), copysize);
|
||||
datapos += copysize;
|
||||
}
|
||||
}
|
||||
|
||||
void VkLevelMeshUploader::UploadPortals()
|
||||
{
|
||||
if (start == 0)
|
||||
{
|
||||
PortalInfo* portals = (PortalInfo*)(data + datapos);
|
||||
for (auto& portal : Mesh->Mesh->StaticMesh->Portals)
|
||||
{
|
||||
PortalInfo info;
|
||||
info.transformation = portal.transformation;
|
||||
*(portals++) = info;
|
||||
}
|
||||
|
||||
size_t copysize = Mesh->Mesh->StaticMesh->Portals.Size() * sizeof(PortalInfo);
|
||||
if (copysize > 0)
|
||||
cmdbuffer->copyBuffer(transferBuffer.get(), Mesh->PortalBuffer.get(), datapos, 0, copysize);
|
||||
datapos += copysize;
|
||||
}
|
||||
}
|
||||
|
||||
void VkLevelMeshUploader::UpdateSizes()
|
||||
{
|
||||
for (LevelSubmesh* submesh : { Mesh->GetMesh()->StaticMesh.get(), Mesh->GetMesh()->DynamicMesh.get() })
|
||||
{
|
||||
SubmeshBufferLocation location;
|
||||
location.Submesh = submesh;
|
||||
location.Vertex.Size = submesh->Mesh.Vertices.Size();
|
||||
location.Index.Size = submesh->Mesh.Indexes.Size();
|
||||
location.Node.Size = (int)submesh->Collision->get_nodes().size();
|
||||
location.SurfaceIndex.Size = submesh->Mesh.SurfaceIndexes.Size();
|
||||
location.Surface.Size = submesh->GetSurfaceCount();
|
||||
location.UniformIndexes.Size = submesh->Mesh.UniformIndexes.Size();
|
||||
location.Uniforms.Size = submesh->Mesh.Uniforms.Size();
|
||||
locations.Push(location);
|
||||
}
|
||||
}
|
||||
|
||||
void VkLevelMeshUploader::UpdateLocations()
|
||||
{
|
||||
for (unsigned int i = 1, count = locations.Size(); i < count; i++)
|
||||
{
|
||||
const SubmeshBufferLocation& prev = locations[i - 1];
|
||||
SubmeshBufferLocation& cur = locations[i];
|
||||
cur.Vertex.Offset = prev.Vertex.Offset + prev.Vertex.Size;
|
||||
cur.Index.Offset = prev.Index.Offset + prev.Index.Size;
|
||||
cur.Node.Offset = prev.Node.Offset + prev.Node.Size;
|
||||
cur.SurfaceIndex.Offset = prev.SurfaceIndex.Offset + prev.SurfaceIndex.Size;
|
||||
cur.Surface.Offset = prev.Surface.Offset + prev.Surface.Size;
|
||||
cur.UniformIndexes.Offset = prev.UniformIndexes.Offset + prev.UniformIndexes.Size;
|
||||
cur.Uniforms.Offset = prev.Uniforms.Offset + prev.Uniforms.Size;
|
||||
|
||||
if (
|
||||
cur.Vertex.Offset + cur.Vertex.Size > Mesh->GetMaxVertexBufferSize() ||
|
||||
cur.Index.Offset + cur.Index.Size > Mesh->GetMaxIndexBufferSize() ||
|
||||
cur.Node.Offset + cur.Node.Size > Mesh->GetMaxNodeBufferSize() ||
|
||||
cur.SurfaceIndex.Offset + cur.SurfaceIndex.Size > Mesh->GetMaxSurfaceIndexBufferSize() ||
|
||||
cur.Surface.Offset + cur.Surface.Size > Mesh->GetMaxSurfaceBufferSize() ||
|
||||
cur.UniformIndexes.Offset + cur.UniformIndexes.Size > Mesh->GetMaxVertexBufferSize() ||
|
||||
cur.Uniforms.Offset + cur.Uniforms.Size > Mesh->GetMaxUniformsBufferSize())
|
||||
{
|
||||
I_FatalError("Dynamic accel struct buffers are too small!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
size_t VkLevelMeshUploader::GetTransferSize()
|
||||
{
|
||||
// Figure out how much memory we need to transfer it to the GPU
|
||||
size_t transferBufferSize = sizeof(CollisionNodeBufferHeader) + sizeof(CollisionNode);
|
||||
for (unsigned int i = start; i < end; i++)
|
||||
{
|
||||
const SubmeshBufferLocation& cur = locations[i];
|
||||
transferBufferSize += cur.Submesh->Mesh.Vertices.Size() * sizeof(FFlatVertex);
|
||||
transferBufferSize += cur.Submesh->Mesh.UniformIndexes.Size() * sizeof(int);
|
||||
transferBufferSize += cur.Submesh->Mesh.Indexes.Size() * sizeof(uint32_t);
|
||||
transferBufferSize += cur.Submesh->Collision->get_nodes().size() * sizeof(CollisionNode);
|
||||
transferBufferSize += cur.Submesh->Mesh.SurfaceIndexes.Size() * sizeof(int);
|
||||
transferBufferSize += cur.Submesh->GetSurfaceCount() * sizeof(SurfaceInfo);
|
||||
transferBufferSize += cur.Submesh->Mesh.Uniforms.Size() * sizeof(SurfaceUniforms);
|
||||
}
|
||||
if (start == 0)
|
||||
transferBufferSize += Mesh->GetMesh()->StaticMesh->Portals.Size() * sizeof(PortalInfo);
|
||||
return transferBufferSize;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,21 +42,22 @@ struct PortalInfo
|
|||
VSMatrix transformation;
|
||||
};
|
||||
|
||||
struct SubmeshBufferRange
|
||||
{
|
||||
int Offset = 0;
|
||||
int Size = 0;
|
||||
};
|
||||
|
||||
struct SubmeshBufferLocation
|
||||
{
|
||||
LevelSubmesh* Submesh = nullptr;
|
||||
int VertexOffset = 0;
|
||||
int VertexSize = 0;
|
||||
int IndexOffset = 0;
|
||||
int IndexSize = 0;
|
||||
int NodeOffset = 0;
|
||||
int NodeSize = 0;
|
||||
int SurfaceIndexOffset = 0;
|
||||
int SurfaceIndexSize = 0;
|
||||
int SurfaceOffset = 0;
|
||||
int SurfaceSize = 0;
|
||||
int UniformsOffset = 0;
|
||||
int UniformsSize = 0;
|
||||
SubmeshBufferRange Vertex;
|
||||
SubmeshBufferRange Index;
|
||||
SubmeshBufferRange Node;
|
||||
SubmeshBufferRange SurfaceIndex;
|
||||
SubmeshBufferRange Surface;
|
||||
SubmeshBufferRange UniformIndexes;
|
||||
SubmeshBufferRange Uniforms;
|
||||
};
|
||||
|
||||
class VkLevelMesh
|
||||
|
|
@ -74,7 +75,7 @@ public:
|
|||
VulkanBuffer* GetNodeBuffer() { return NodeBuffer.get(); }
|
||||
VulkanBuffer* GetSurfaceIndexBuffer() { return SurfaceIndexBuffer.get(); }
|
||||
VulkanBuffer* GetSurfaceBuffer() { return SurfaceBuffer.get(); }
|
||||
VulkanBuffer* GetSurfaceUniformsBuffer() { return SurfaceUniformsBuffer.get(); }
|
||||
VulkanBuffer* GetUniformsBuffer() { return UniformsBuffer.get(); }
|
||||
VulkanBuffer* GetPortalBuffer() { return PortalBuffer.get(); }
|
||||
|
||||
LevelMesh* GetMesh() { return Mesh; }
|
||||
|
|
@ -118,7 +119,7 @@ private:
|
|||
std::unique_ptr<VulkanBuffer> IndexBuffer;
|
||||
std::unique_ptr<VulkanBuffer> SurfaceIndexBuffer;
|
||||
std::unique_ptr<VulkanBuffer> SurfaceBuffer;
|
||||
std::unique_ptr<VulkanBuffer> SurfaceUniformsBuffer;
|
||||
std::unique_ptr<VulkanBuffer> UniformsBuffer;
|
||||
std::unique_ptr<VulkanBuffer> PortalBuffer;
|
||||
|
||||
std::unique_ptr<VulkanBuffer> NodeBuffer;
|
||||
|
|
@ -142,4 +143,38 @@ private:
|
|||
std::unique_ptr<VulkanBuffer> AccelStructBuffer;
|
||||
std::unique_ptr<VulkanAccelerationStructure> AccelStruct;
|
||||
} TopLevelAS;
|
||||
|
||||
friend class VkLevelMeshUploader;
|
||||
};
|
||||
|
||||
class VkLevelMeshUploader
|
||||
{
|
||||
public:
|
||||
VkLevelMeshUploader(VkLevelMesh* mesh);
|
||||
|
||||
void Upload(bool dynamicOnly);
|
||||
|
||||
private:
|
||||
void BeginTransfer(size_t transferBufferSize);
|
||||
void EndTransfer(size_t transferBufferSize);
|
||||
void UploadNodes();
|
||||
void UploadVertices();
|
||||
void UploadUniformIndexes();
|
||||
void UploadIndexes();
|
||||
void UploadSurfaceIndexes();
|
||||
void UploadSurfaces();
|
||||
void UploadUniforms();
|
||||
void UploadPortals();
|
||||
void UpdateSizes();
|
||||
void UpdateLocations();
|
||||
size_t GetTransferSize();
|
||||
|
||||
VkLevelMesh* Mesh;
|
||||
TArray<SubmeshBufferLocation> locations;
|
||||
unsigned int start = 0;
|
||||
unsigned int end = 0;
|
||||
uint8_t* data = nullptr;
|
||||
size_t datapos = 0;
|
||||
VulkanCommandBuffer* cmdbuffer = nullptr;
|
||||
std::unique_ptr<VulkanBuffer> transferBuffer;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -190,7 +190,7 @@ void VkLightmapper::Render()
|
|||
if (targetSurface->Submesh != mesh->StaticMesh.get())
|
||||
{
|
||||
surfaceIndexOffset = mesh->StaticMesh->GetSurfaceCount();
|
||||
firstIndexOffset = mesh->StaticMesh->Mesh.Elements.Size();
|
||||
firstIndexOffset = mesh->StaticMesh->Mesh.Indexes.Size();
|
||||
}
|
||||
|
||||
LightmapRaytracePC pc;
|
||||
|
|
|
|||
|
|
@ -251,7 +251,7 @@ void DoomLevelMesh::DumpMesh(const FString& objFilename, const FString& mtlFilen
|
|||
auto f = fopen(objFilename.GetChars(), "w");
|
||||
|
||||
fprintf(f, "# DoomLevelMesh debug export\n");
|
||||
fprintf(f, "# MeshVertices: %u, MeshElements: %u, Surfaces: %u\n", submesh->Mesh.Vertices.Size(), submesh->Mesh.Elements.Size(), submesh->Surfaces.Size());
|
||||
fprintf(f, "# Vertices: %u, Indexes: %u, Surfaces: %u\n", submesh->Mesh.Vertices.Size(), submesh->Mesh.Indexes.Size(), submesh->Surfaces.Size());
|
||||
fprintf(f, "mtllib %s\n", mtlFilename.GetChars());
|
||||
|
||||
double scale = 1 / 10.0;
|
||||
|
|
@ -294,7 +294,7 @@ void DoomLevelMesh::DumpMesh(const FString& objFilename, const FString& mtlFilen
|
|||
bool useErrorMaterial = false;
|
||||
int highestUsedAtlasPage = -1;
|
||||
|
||||
for (unsigned i = 0, count = submesh->Mesh.Elements.Size(); i + 2 < count; i += 3)
|
||||
for (unsigned i = 0, count = submesh->Mesh.Indexes.Size(); i + 2 < count; i += 3)
|
||||
{
|
||||
auto index = submesh->Mesh.SurfaceIndexes[i / 3];
|
||||
|
||||
|
|
@ -324,9 +324,9 @@ void DoomLevelMesh::DumpMesh(const FString& objFilename, const FString& mtlFilen
|
|||
|
||||
// fprintf(f, "f %d %d %d\n", MeshElements[i] + 1, MeshElements[i + 1] + 1, MeshElements[i + 2] + 1);
|
||||
fprintf(f, "f %d/%d %d/%d %d/%d\n",
|
||||
submesh->Mesh.Elements[i + 0] + 1, submesh->Mesh.Elements[i + 0] + 1,
|
||||
submesh->Mesh.Elements[i + 1] + 1, submesh->Mesh.Elements[i + 1] + 1,
|
||||
submesh->Mesh.Elements[i + 2] + 1, submesh->Mesh.Elements[i + 2] + 1);
|
||||
submesh->Mesh.Indexes[i + 0] + 1, submesh->Mesh.Indexes[i + 0] + 1,
|
||||
submesh->Mesh.Indexes[i + 1] + 1, submesh->Mesh.Indexes[i + 1] + 1,
|
||||
submesh->Mesh.Indexes[i + 2] + 1, submesh->Mesh.Indexes[i + 2] + 1);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ void DoomLevelSubmesh::Reset()
|
|||
Surfaces.Clear();
|
||||
WallPortals.Clear();
|
||||
Mesh.Vertices.Clear();
|
||||
Mesh.Elements.Clear();
|
||||
Mesh.Indexes.Clear();
|
||||
Mesh.SurfaceIndexes.Clear();
|
||||
Mesh.UniformIndexes.Clear();
|
||||
Mesh.Uniforms.Clear();
|
||||
|
|
@ -328,7 +328,7 @@ void DoomLevelSubmesh::CreateIndexes()
|
|||
{
|
||||
LevelSubmeshDrawRange range;
|
||||
range.PipelineID = it.first >> 32;
|
||||
range.Start = Mesh.Elements.Size();
|
||||
range.Start = Mesh.Indexes.Size();
|
||||
for (unsigned int i : it.second)
|
||||
{
|
||||
DoomLevelMeshSurface& s = Surfaces[i];
|
||||
|
|
@ -337,7 +337,7 @@ void DoomLevelSubmesh::CreateIndexes()
|
|||
FFlatVertex* verts = &Mesh.Vertices[pos];
|
||||
|
||||
s.Vertices = verts;
|
||||
s.startElementIndex = Mesh.Elements.Size();
|
||||
s.startElementIndex = Mesh.Indexes.Size();
|
||||
s.numElements = 0;
|
||||
|
||||
if (s.Type == ST_CEILING)
|
||||
|
|
@ -346,9 +346,9 @@ void DoomLevelSubmesh::CreateIndexes()
|
|||
{
|
||||
if (!IsDegenerate(verts[0].fPos(), verts[j - 1].fPos(), verts[j].fPos()))
|
||||
{
|
||||
Mesh.Elements.Push(pos);
|
||||
Mesh.Elements.Push(pos + j - 1);
|
||||
Mesh.Elements.Push(pos + j);
|
||||
Mesh.Indexes.Push(pos);
|
||||
Mesh.Indexes.Push(pos + j - 1);
|
||||
Mesh.Indexes.Push(pos + j);
|
||||
Mesh.SurfaceIndexes.Push((int)i);
|
||||
s.numElements += 3;
|
||||
}
|
||||
|
|
@ -360,9 +360,9 @@ void DoomLevelSubmesh::CreateIndexes()
|
|||
{
|
||||
if (!IsDegenerate(verts[0].fPos(), verts[j - 1].fPos(), verts[j].fPos()))
|
||||
{
|
||||
Mesh.Elements.Push(pos + j);
|
||||
Mesh.Elements.Push(pos + j - 1);
|
||||
Mesh.Elements.Push(pos);
|
||||
Mesh.Indexes.Push(pos + j);
|
||||
Mesh.Indexes.Push(pos + j - 1);
|
||||
Mesh.Indexes.Push(pos);
|
||||
Mesh.SurfaceIndexes.Push((int)i);
|
||||
s.numElements += 3;
|
||||
}
|
||||
|
|
@ -372,23 +372,23 @@ void DoomLevelSubmesh::CreateIndexes()
|
|||
{
|
||||
if (!IsDegenerate(verts[0].fPos(), verts[2].fPos(), verts[1].fPos()))
|
||||
{
|
||||
Mesh.Elements.Push(pos + 0);
|
||||
Mesh.Elements.Push(pos + 1);
|
||||
Mesh.Elements.Push(pos + 2);
|
||||
Mesh.Indexes.Push(pos + 0);
|
||||
Mesh.Indexes.Push(pos + 1);
|
||||
Mesh.Indexes.Push(pos + 2);
|
||||
Mesh.SurfaceIndexes.Push((int)i);
|
||||
s.numElements += 3;
|
||||
}
|
||||
if (!IsDegenerate(verts[0].fPos(), verts[2].fPos(), verts[3].fPos()))
|
||||
{
|
||||
Mesh.Elements.Push(pos + 0);
|
||||
Mesh.Elements.Push(pos + 2);
|
||||
Mesh.Elements.Push(pos + 3);
|
||||
Mesh.Indexes.Push(pos + 0);
|
||||
Mesh.Indexes.Push(pos + 2);
|
||||
Mesh.Indexes.Push(pos + 3);
|
||||
Mesh.SurfaceIndexes.Push((int)i);
|
||||
s.numElements += 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
range.Count = Mesh.Elements.Size() - range.Start;
|
||||
range.Count = Mesh.Indexes.Size() - range.Start;
|
||||
|
||||
if ((it.first & 1) == 0)
|
||||
DrawList.Push(range);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue