Fix node buffers not working for the rayquery polyfill shader path
Rearrange how the upload code is done for the level mesh
This commit is contained in:
parent
40509ef845
commit
757320c5bc
5 changed files with 232 additions and 187 deletions
|
|
@ -29,7 +29,7 @@ CVAR(Float, lm_scale, 1.0, CVAR_NOSAVE);
|
|||
|
||||
VkLightmap::VkLightmap(VulkanRenderDevice* fb) : fb(fb)
|
||||
{
|
||||
useRayQuery = fb->GetDevice()->PhysicalDevice.Features.RayQuery.rayQuery;
|
||||
useRayQuery = fb->GetDevice()->SupportsExtension(VK_KHR_RAY_QUERY_EXTENSION_NAME) && fb->GetDevice()->PhysicalDevice.Features.RayQuery.rayQuery;
|
||||
|
||||
templightlist.Resize(128);
|
||||
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@
|
|||
|
||||
VkRaytrace::VkRaytrace(VulkanRenderDevice* fb) : fb(fb)
|
||||
{
|
||||
useRayQuery = fb->GetDevice()->SupportsExtension(VK_KHR_RAY_QUERY_EXTENSION_NAME);
|
||||
useRayQuery = fb->GetDevice()->SupportsExtension(VK_KHR_RAY_QUERY_EXTENSION_NAME) && fb->GetDevice()->PhysicalDevice.Features.RayQuery.rayQuery;
|
||||
|
||||
SetLevelMesh(nullptr);
|
||||
}
|
||||
|
|
@ -70,10 +70,9 @@ void VkRaytrace::Reset()
|
|||
void VkRaytrace::CreateVulkanObjects()
|
||||
{
|
||||
CreateBuffers();
|
||||
UploadMeshes(false);
|
||||
if (useRayQuery)
|
||||
{
|
||||
UploadStatic();
|
||||
UploadDynamic();
|
||||
CreateStaticBLAS();
|
||||
CreateDynamicBLAS();
|
||||
CreateTopLevelAS();
|
||||
|
|
@ -82,70 +81,234 @@ void VkRaytrace::CreateVulkanObjects()
|
|||
|
||||
void VkRaytrace::BeginFrame()
|
||||
{
|
||||
UploadMeshes(true);
|
||||
if (useRayQuery)
|
||||
{
|
||||
UploadDynamic();
|
||||
UpdateDynamicBLAS();
|
||||
UpdateTopLevelAS();
|
||||
}
|
||||
}
|
||||
|
||||
void VkRaytrace::UploadStatic()
|
||||
void VkRaytrace::UploadMeshes(bool dynamicOnly)
|
||||
{
|
||||
auto submesh = Mesh->StaticMesh.get();
|
||||
TArray<SubmeshBufferLocation> locations(2);
|
||||
|
||||
Vertices = TArray<SurfaceVertex>(GetMaxVertexBufferSize());
|
||||
|
||||
for (int i = 0, count = submesh->MeshVertices.Size(); i < count; ++i)
|
||||
Vertices.Push({ { submesh->MeshVertices[i], 1.0f }, submesh->MeshVertexUVs[i], float(i), i + 10000.0f });
|
||||
|
||||
CollisionNodeBufferHeader nodesHeader;
|
||||
nodesHeader.root = submesh->Collision->get_root();
|
||||
TArray<CollisionNode> nodes = CreateCollisionNodes(submesh);
|
||||
|
||||
TArray<SurfaceInfo> surfaceInfo = CreateSurfaceInfo(submesh);
|
||||
|
||||
TArray<PortalInfo> portalInfo;
|
||||
for (auto& portal : submesh->Portals)
|
||||
// Find submesh buffer sizes
|
||||
for (LevelSubmesh* submesh : { Mesh->StaticMesh.get(), Mesh->DynamicMesh.get() })
|
||||
{
|
||||
PortalInfo info;
|
||||
info.transformation = portal.transformation;
|
||||
portalInfo.Push(info);
|
||||
SubmeshBufferLocation location;
|
||||
location.Submesh = submesh;
|
||||
location.VertexSize = submesh->MeshVertices.Size();
|
||||
location.IndexSize = submesh->MeshElements.Size();
|
||||
location.NodeSize = (int)submesh->Collision->get_nodes().size();
|
||||
location.SurfaceIndexSize = submesh->MeshSurfaceIndexes.Size();
|
||||
location.SurfaceSize = submesh->GetSurfaceCount();
|
||||
locations.Push(location);
|
||||
}
|
||||
|
||||
auto transferBuffer = BufferTransfer()
|
||||
.AddBuffer(VertexBuffer.get(), Vertices.Data(), Vertices.Size() * sizeof(SurfaceVertex))
|
||||
.AddBuffer(IndexBuffer.get(), submesh->MeshElements.Data(), (size_t)submesh->MeshElements.Size() * sizeof(uint32_t))
|
||||
.AddBuffer(NodeBuffer.get(), &nodesHeader, sizeof(CollisionNodeBufferHeader), nodes.Data(), nodes.Size() * sizeof(CollisionNode))
|
||||
.AddBuffer(SurfaceIndexBuffer.get(), submesh->MeshSurfaceIndexes.Data(), submesh->MeshSurfaceIndexes.Size() * sizeof(int))
|
||||
.AddBuffer(SurfaceBuffer.get(), surfaceInfo.Data(), surfaceInfo.Size() * sizeof(SurfaceInfo))
|
||||
.AddBuffer(PortalBuffer.get(), portalInfo.Data(), portalInfo.Size() * sizeof(PortalInfo))
|
||||
.Execute(fb->GetDevice(), fb->GetCommands()->GetTransferCommands());
|
||||
// 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;
|
||||
|
||||
fb->GetCommands()->TransferDeleteList->Add(std::move(transferBuffer));
|
||||
if (
|
||||
cur.VertexOffset + cur.VertexSize > GetMaxVertexBufferSize() ||
|
||||
cur.IndexOffset + cur.IndexSize > GetMaxIndexBufferSize() ||
|
||||
cur.NodeOffset + cur.NodeSize > GetMaxNodeBufferSize() ||
|
||||
cur.SurfaceOffset + cur.SurfaceSize > GetMaxSurfaceBufferSize() ||
|
||||
cur.SurfaceIndexOffset + cur.SurfaceIndexSize > GetMaxSurfaceIndexBufferSize())
|
||||
{
|
||||
I_FatalError("Dynamic accel struct buffers are too small!");
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
unsigned int start = dynamicOnly;
|
||||
unsigned int end = locations.Size();
|
||||
|
||||
void VkRaytrace::UploadDynamic()
|
||||
{
|
||||
auto submesh = Mesh->DynamicMesh.get();
|
||||
// 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->MeshVertices.Size() * sizeof(SurfaceVertex);
|
||||
transferBufferSize += cur.Submesh->MeshElements.Size() * sizeof(uint32_t);
|
||||
transferBufferSize += cur.Submesh->Collision->get_nodes().size() * sizeof(CollisionNode);
|
||||
transferBufferSize += cur.Submesh->MeshSurfaceIndexes.Size() * sizeof(int);
|
||||
transferBufferSize += cur.Submesh->GetSurfaceCount() * sizeof(SurfaceInfo);
|
||||
}
|
||||
if (!dynamicOnly)
|
||||
transferBufferSize += Mesh->StaticMesh->Portals.Size() * sizeof(PortalInfo);
|
||||
|
||||
Vertices.Resize(Mesh->StaticMesh->MeshVertices.Size());
|
||||
// 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());
|
||||
|
||||
for (int i = 0, count = submesh->MeshVertices.Size(); i < count; ++i)
|
||||
Vertices.Push({ { submesh->MeshVertices[i], 1.0f }, submesh->MeshVertexUVs[i], float(i), i + 10000.0f });
|
||||
uint8_t* data = (uint8_t*)transferBuffer->Map(0, transferBufferSize);
|
||||
size_t datapos = 0;
|
||||
|
||||
TArray<SurfaceInfo> surfaceInfo = CreateSurfaceInfo(submesh);
|
||||
// Copy node buffer header and create a root node that merges the static and dynamic AABB trees
|
||||
{
|
||||
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];
|
||||
|
||||
auto transferBuffer = BufferTransfer()
|
||||
.AddBuffer(VertexBuffer.get(), Mesh->StaticMesh->MeshVertices.Size() * sizeof(SurfaceVertex), Vertices.Data() + Mesh->StaticMesh->MeshVertices.Size(), Vertices.Size() * sizeof(SurfaceVertex))
|
||||
.AddBuffer(IndexBuffer.get(), Mesh->StaticMesh->MeshElements.Size() * sizeof(uint32_t), submesh->MeshElements.Data(), (size_t)submesh->MeshElements.Size() * sizeof(uint32_t))
|
||||
.AddBuffer(SurfaceIndexBuffer.get(), Mesh->StaticMesh->MeshSurfaceIndexes.Size() * sizeof(int), submesh->MeshSurfaceIndexes.Data(), submesh->MeshSurfaceIndexes.Size() * sizeof(int))
|
||||
.AddBuffer(SurfaceBuffer.get(), Mesh->StaticMesh->GetSurfaceCount() * sizeof(SurfaceInfo), surfaceInfo.Data(), surfaceInfo.Size() * sizeof(SurfaceInfo))
|
||||
.Execute(fb->GetDevice(), fb->GetCommands()->GetTransferCommands());
|
||||
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));
|
||||
|
||||
datapos += sizeof(CollisionNodeBufferHeader) + sizeof(CollisionNode);
|
||||
}
|
||||
|
||||
// Copy vertices
|
||||
for (unsigned int i = start; i < end; i++)
|
||||
{
|
||||
const SubmeshBufferLocation& cur = locations[i];
|
||||
auto submesh = cur.Submesh;
|
||||
|
||||
SurfaceVertex* vertices = (SurfaceVertex*)(data + datapos);
|
||||
for (int j = 0, count = submesh->MeshVertices.Size(); j < count; ++j)
|
||||
*(vertices++) = { { submesh->MeshVertices[j], 1.0f }, submesh->MeshVertexUVs[j], float(j), j + 10000.0f };
|
||||
|
||||
size_t copysize = submesh->MeshVertices.Size() * sizeof(SurfaceVertex);
|
||||
cmdbuffer->copyBuffer(transferBuffer.get(), VertexBuffer.get(), datapos, cur.VertexOffset * sizeof(SurfaceVertex), 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->MeshElements.Size(); j < count; ++j)
|
||||
*(indexes++) = cur.VertexOffset + submesh->MeshElements[j];
|
||||
|
||||
size_t copysize = submesh->MeshElements.Size() * sizeof(uint32_t);
|
||||
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);
|
||||
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->MeshSurfaceIndexes.Size(); j < count; ++j)
|
||||
*(indexes++) = cur.SurfaceIndexOffset + submesh->MeshSurfaceIndexes[j];
|
||||
|
||||
size_t copysize = submesh->MeshSurfaceIndexes.Size() * sizeof(int);
|
||||
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 = surface->plane.XYZ();
|
||||
info.PortalIndex = surface->portalIndex;
|
||||
info.SamplingDistance = (float)surface->sampleDimension;
|
||||
info.Sky = surface->bSky;
|
||||
if (surface->texture.isValid())
|
||||
{
|
||||
auto mat = FMaterial::ValidateTexture(TexMan.GetGameTexture(surface->texture), 0);
|
||||
info.TextureIndex = fb->GetBindlessTextureIndex(mat, CLAMP_NONE, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
info.TextureIndex = -1;
|
||||
}
|
||||
info.Alpha = surface->alpha;
|
||||
|
||||
*(surfaces++) = info;
|
||||
}
|
||||
|
||||
size_t copysize = submesh->GetSurfaceCount() * sizeof(SurfaceInfo);
|
||||
cmdbuffer->copyBuffer(transferBuffer.get(), SurfaceBuffer.get(), datapos, cur.SurfaceOffset * sizeof(SurfaceInfo), 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);
|
||||
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));
|
||||
|
||||
|
|
@ -166,7 +329,7 @@ int VkRaytrace::GetMaxIndexBufferSize()
|
|||
|
||||
int VkRaytrace::GetMaxNodeBufferSize()
|
||||
{
|
||||
return (int)Mesh->StaticMesh->Collision->get_nodes().size() + MaxDynamicNodes;
|
||||
return (int)Mesh->StaticMesh->Collision->get_nodes().size() + MaxDynamicNodes + 1; // + 1 for the merge root node
|
||||
}
|
||||
|
||||
int VkRaytrace::GetMaxSurfaceBufferSize()
|
||||
|
|
@ -242,11 +405,11 @@ VkRaytrace::BLAS VkRaytrace::CreateBLAS(LevelSubmesh* submesh, bool preferFastBu
|
|||
accelStructBLDesc.flags = VK_GEOMETRY_OPAQUE_BIT_KHR;
|
||||
accelStructBLDesc.geometry.triangles = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR };
|
||||
accelStructBLDesc.geometry.triangles.vertexFormat = VK_FORMAT_R32G32B32A32_SFLOAT;
|
||||
accelStructBLDesc.geometry.triangles.vertexData.deviceAddress = VertexBuffer->GetDeviceAddress() + vertexOffset * sizeof(SurfaceVertex);
|
||||
accelStructBLDesc.geometry.triangles.vertexData.deviceAddress = VertexBuffer->GetDeviceAddress();
|
||||
accelStructBLDesc.geometry.triangles.vertexStride = sizeof(SurfaceVertex);
|
||||
accelStructBLDesc.geometry.triangles.indexType = VK_INDEX_TYPE_UINT32;
|
||||
accelStructBLDesc.geometry.triangles.indexData.deviceAddress = IndexBuffer->GetDeviceAddress() + indexOffset * sizeof(uint32_t);
|
||||
accelStructBLDesc.geometry.triangles.maxVertex = submesh->MeshVertices.Size() - 1;
|
||||
accelStructBLDesc.geometry.triangles.maxVertex = vertexOffset + submesh->MeshVertices.Size() - 1;
|
||||
|
||||
buildInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR;
|
||||
buildInfo.flags = preferFastBuild ? VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_KHR : VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR;
|
||||
|
|
@ -474,111 +637,3 @@ void VkRaytrace::UpdateTopLevelAS()
|
|||
.Execute(fb->GetCommands()->GetTransferCommands(), VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
|
||||
}
|
||||
|
||||
TArray<SurfaceInfo> VkRaytrace::CreateSurfaceInfo(LevelSubmesh* submesh)
|
||||
{
|
||||
TArray<SurfaceInfo> surfaceInfo(submesh->GetSurfaceCount());
|
||||
for (int i = 0, count = submesh->GetSurfaceCount(); i < count; i++)
|
||||
{
|
||||
LevelMeshSurface* surface = submesh->GetSurface(i);
|
||||
|
||||
SurfaceInfo info;
|
||||
info.Normal = surface->plane.XYZ();
|
||||
info.PortalIndex = surface->portalIndex;
|
||||
info.SamplingDistance = (float)surface->sampleDimension;
|
||||
info.Sky = surface->bSky;
|
||||
|
||||
if (surface->texture.isValid())
|
||||
{
|
||||
auto mat = FMaterial::ValidateTexture(TexMan.GetGameTexture(surface->texture), 0);
|
||||
info.TextureIndex = fb->GetBindlessTextureIndex(mat, CLAMP_NONE, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
info.TextureIndex = -1;
|
||||
}
|
||||
|
||||
info.Alpha = surface->alpha;
|
||||
|
||||
surfaceInfo.Push(info);
|
||||
}
|
||||
return surfaceInfo;
|
||||
}
|
||||
|
||||
TArray<CollisionNode> VkRaytrace::CreateCollisionNodes(LevelSubmesh* submesh)
|
||||
{
|
||||
TArray<CollisionNode> nodes(submesh->Collision->get_nodes().size());
|
||||
for (const auto& node : submesh->Collision->get_nodes())
|
||||
{
|
||||
CollisionNode info;
|
||||
info.center = node.aabb.Center;
|
||||
info.extents = node.aabb.Extents;
|
||||
info.left = node.left;
|
||||
info.right = node.right;
|
||||
info.element_index = node.element_index;
|
||||
nodes.Push(info);
|
||||
}
|
||||
if (nodes.Size() == 0) // vulkan doesn't support zero byte buffers
|
||||
nodes.Push(CollisionNode());
|
||||
return nodes;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
BufferTransfer& BufferTransfer::AddBuffer(VulkanBuffer* buffer, size_t offset, const void* data, size_t size)
|
||||
{
|
||||
bufferCopies.push_back({ buffer, offset, data, size, nullptr, 0 });
|
||||
return *this;
|
||||
}
|
||||
|
||||
BufferTransfer& BufferTransfer::AddBuffer(VulkanBuffer* buffer, const void* data, size_t size)
|
||||
{
|
||||
bufferCopies.push_back({ buffer, 0, data, size, nullptr, 0 });
|
||||
return *this;
|
||||
}
|
||||
|
||||
BufferTransfer& BufferTransfer::AddBuffer(VulkanBuffer* buffer, const void* data0, size_t size0, const void* data1, size_t size1)
|
||||
{
|
||||
bufferCopies.push_back({ buffer, 0, data0, size0, data1, size1 });
|
||||
return *this;
|
||||
}
|
||||
|
||||
std::unique_ptr<VulkanBuffer> BufferTransfer::Execute(VulkanDevice* device, VulkanCommandBuffer* cmdbuffer)
|
||||
{
|
||||
size_t transferbuffersize = 0;
|
||||
for (const auto& copy : bufferCopies)
|
||||
transferbuffersize += copy.size0 + copy.size1;
|
||||
|
||||
if (transferbuffersize == 0)
|
||||
return nullptr;
|
||||
|
||||
auto transferBuffer = BufferBuilder()
|
||||
.Usage(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY)
|
||||
.Size(transferbuffersize)
|
||||
.DebugName("BufferTransfer.transferBuffer")
|
||||
.Create(device);
|
||||
|
||||
uint8_t* data = (uint8_t*)transferBuffer->Map(0, transferbuffersize);
|
||||
size_t pos = 0;
|
||||
for (const auto& copy : bufferCopies)
|
||||
{
|
||||
memcpy(data + pos, copy.data0, copy.size0);
|
||||
pos += copy.size0;
|
||||
memcpy(data + pos, copy.data1, copy.size1);
|
||||
pos += copy.size1;
|
||||
}
|
||||
transferBuffer->Unmap();
|
||||
|
||||
pos = 0;
|
||||
for (const auto& copy : bufferCopies)
|
||||
{
|
||||
if (copy.size0 > 0)
|
||||
cmdbuffer->copyBuffer(transferBuffer.get(), copy.buffer, pos, copy.offset, copy.size0);
|
||||
pos += copy.size0;
|
||||
|
||||
if (copy.size1 > 0)
|
||||
cmdbuffer->copyBuffer(transferBuffer.get(), copy.buffer, pos, copy.offset + copy.size0, copy.size1);
|
||||
pos += copy.size1;
|
||||
}
|
||||
|
||||
return transferBuffer;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,6 +49,21 @@ struct PortalInfo
|
|||
VSMatrix transformation;
|
||||
};
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
class VkRaytrace
|
||||
{
|
||||
public:
|
||||
|
|
@ -79,8 +94,7 @@ private:
|
|||
void CreateStaticBLAS();
|
||||
void CreateDynamicBLAS();
|
||||
void CreateTopLevelAS();
|
||||
void UploadStatic();
|
||||
void UploadDynamic();
|
||||
void UploadMeshes(bool dynamicOnly);
|
||||
void UpdateDynamicBLAS();
|
||||
void UpdateTopLevelAS();
|
||||
|
||||
|
|
@ -92,9 +106,6 @@ private:
|
|||
int GetMaxSurfaceBufferSize();
|
||||
int GetMaxSurfaceIndexBufferSize();
|
||||
|
||||
TArray<SurfaceInfo> CreateSurfaceInfo(LevelSubmesh* submesh);
|
||||
TArray<CollisionNode> CreateCollisionNodes(LevelSubmesh* submesh);
|
||||
|
||||
VulkanRenderDevice* fb = nullptr;
|
||||
|
||||
bool useRayQuery = true;
|
||||
|
|
@ -129,24 +140,3 @@ private:
|
|||
std::unique_ptr<VulkanAccelerationStructure> AccelStruct;
|
||||
} TopLevelAS;
|
||||
};
|
||||
|
||||
class BufferTransfer
|
||||
{
|
||||
public:
|
||||
BufferTransfer& AddBuffer(VulkanBuffer* buffer, size_t offset, const void* data, size_t size);
|
||||
BufferTransfer& AddBuffer(VulkanBuffer* buffer, const void* data, size_t size);
|
||||
BufferTransfer& AddBuffer(VulkanBuffer* buffer, const void* data0, size_t size0, const void* data1, size_t size1);
|
||||
std::unique_ptr<VulkanBuffer> Execute(VulkanDevice* device, VulkanCommandBuffer* cmdbuffer);
|
||||
|
||||
private:
|
||||
struct BufferCopy
|
||||
{
|
||||
VulkanBuffer* buffer;
|
||||
size_t offset;
|
||||
const void* data0;
|
||||
size_t size0;
|
||||
const void* data1;
|
||||
size_t size1;
|
||||
};
|
||||
std::vector<BufferCopy> bufferCopies;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@ void VkDescriptorSetManager::UpdateFixedSet()
|
|||
WriteDescriptors update;
|
||||
update.AddCombinedImageSampler(FixedSet.get(), 0, fb->GetTextureManager()->Shadowmap.View.get(), fb->GetSamplerManager()->ShadowmapSampler.get(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
||||
update.AddCombinedImageSampler(FixedSet.get(), 1, fb->GetTextureManager()->Lightmap.View.get(), fb->GetSamplerManager()->LightmapSampler.get(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
||||
if (fb->GetDevice()->SupportsExtension(VK_KHR_RAY_QUERY_EXTENSION_NAME))
|
||||
if (fb->GetDevice()->SupportsExtension(VK_KHR_RAY_QUERY_EXTENSION_NAME) && fb->GetDevice()->PhysicalDevice.Features.RayQuery.rayQuery)
|
||||
{
|
||||
update.AddAccelerationStructure(FixedSet.get(), 2, fb->GetRaytrace()->GetAccelStruct());
|
||||
}
|
||||
|
|
@ -270,7 +270,7 @@ void VkDescriptorSetManager::CreateFixedSetLayout()
|
|||
DescriptorSetLayoutBuilder builder;
|
||||
builder.AddBinding(0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||
builder.AddBinding(1, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||
if (fb->GetDevice()->SupportsExtension(VK_KHR_RAY_QUERY_EXTENSION_NAME))
|
||||
if (fb->GetDevice()->SupportsExtension(VK_KHR_RAY_QUERY_EXTENSION_NAME) && fb->GetDevice()->PhysicalDevice.Features.RayQuery.rayQuery)
|
||||
{
|
||||
builder.AddBinding(2, VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||
}
|
||||
|
|
@ -298,7 +298,7 @@ void VkDescriptorSetManager::CreateFixedSetPool()
|
|||
{
|
||||
DescriptorPoolBuilder poolbuilder;
|
||||
poolbuilder.AddPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2 * maxSets);
|
||||
if (fb->GetDevice()->SupportsExtension(VK_KHR_RAY_QUERY_EXTENSION_NAME))
|
||||
if (fb->GetDevice()->SupportsExtension(VK_KHR_RAY_QUERY_EXTENSION_NAME) && fb->GetDevice()->PhysicalDevice.Features.RayQuery.rayQuery)
|
||||
{
|
||||
poolbuilder.AddPoolSize(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 1 * maxSets);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -163,7 +163,7 @@ std::unique_ptr<VulkanShader> VkShaderManager::LoadVertShader(FString shadername
|
|||
std::unique_ptr<VulkanShader> VkShaderManager::LoadFragShader(FString shadername, const char *frag_lump, const char *material_lump, const char* mateffect_lump, const char *light_lump, const char *defines, const VkShaderKey& key)
|
||||
{
|
||||
FString definesBlock;
|
||||
if (fb->GetDevice()->SupportsExtension(VK_KHR_RAY_QUERY_EXTENSION_NAME)) definesBlock << "\n#define SUPPORTS_RAYQUERY\n";
|
||||
if (fb->GetDevice()->SupportsExtension(VK_KHR_RAY_QUERY_EXTENSION_NAME) && fb->GetDevice()->PhysicalDevice.Features.RayQuery.rayQuery) definesBlock << "\n#define SUPPORTS_RAYQUERY\n";
|
||||
definesBlock << defines;
|
||||
definesBlock << "\n#define MAX_STREAM_DATA " << std::to_string(MAX_STREAM_DATA).c_str() << "\n";
|
||||
definesBlock << "#define MAX_LIGHT_DATA " << std::to_string(MAX_LIGHT_DATA).c_str() << "\n";
|
||||
|
|
@ -270,7 +270,7 @@ FString VkShaderManager::GetVersionBlock()
|
|||
|
||||
versionBlock << "#extension GL_GOOGLE_include_directive : enable\n";
|
||||
|
||||
if (fb->GetDevice()->SupportsExtension(VK_KHR_RAY_QUERY_EXTENSION_NAME))
|
||||
if (fb->GetDevice()->SupportsExtension(VK_KHR_RAY_QUERY_EXTENSION_NAME) && fb->GetDevice()->PhysicalDevice.Features.RayQuery.rayQuery)
|
||||
{
|
||||
versionBlock << "#extension GL_EXT_ray_query : enable\n";
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue