mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-29 23:33:00 +00:00
Add support for gl_light_raytrace for cards that do not support rayquery
This commit is contained in:
parent
16ad25b382
commit
447932025f
5 changed files with 369 additions and 36 deletions
|
@ -104,7 +104,15 @@ void VkDescriptorSetManager::UpdateFixedSet()
|
||||||
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(), 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);
|
update.AddCombinedImageSampler(FixedSet.get(), 1, fb->GetTextureManager()->Lightmap.View.get(), fb->GetSamplerManager()->LightmapSampler.get(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
||||||
if (fb->device->SupportsExtension(VK_KHR_RAY_QUERY_EXTENSION_NAME))
|
if (fb->device->SupportsExtension(VK_KHR_RAY_QUERY_EXTENSION_NAME))
|
||||||
|
{
|
||||||
update.AddAccelerationStructure(FixedSet.get(), 2, fb->GetRaytrace()->GetAccelStruct());
|
update.AddAccelerationStructure(FixedSet.get(), 2, fb->GetRaytrace()->GetAccelStruct());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
update.AddBuffer(FixedSet.get(), 2, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetRaytrace()->GetNodeBuffer());
|
||||||
|
update.AddBuffer(FixedSet.get(), 3, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetRaytrace()->GetVertexBuffer());
|
||||||
|
update.AddBuffer(FixedSet.get(), 4, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetRaytrace()->GetIndexBuffer());
|
||||||
|
}
|
||||||
update.Execute(fb->device.get());
|
update.Execute(fb->device.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -264,7 +272,15 @@ void VkDescriptorSetManager::CreateFixedSetLayout()
|
||||||
builder.AddBinding(0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
|
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);
|
builder.AddBinding(1, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||||
if (fb->device->SupportsExtension(VK_KHR_RAY_QUERY_EXTENSION_NAME))
|
if (fb->device->SupportsExtension(VK_KHR_RAY_QUERY_EXTENSION_NAME))
|
||||||
|
{
|
||||||
builder.AddBinding(2, VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
|
builder.AddBinding(2, VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
builder.AddBinding(2, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||||
|
builder.AddBinding(3, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||||
|
builder.AddBinding(4, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||||
|
}
|
||||||
builder.DebugName("VkDescriptorSetManager.FixedSetLayout");
|
builder.DebugName("VkDescriptorSetManager.FixedSetLayout");
|
||||||
FixedSetLayout = builder.Create(fb->device.get());
|
FixedSetLayout = builder.Create(fb->device.get());
|
||||||
}
|
}
|
||||||
|
@ -284,7 +300,13 @@ void VkDescriptorSetManager::CreateFixedSetPool()
|
||||||
DescriptorPoolBuilder poolbuilder;
|
DescriptorPoolBuilder poolbuilder;
|
||||||
poolbuilder.AddPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2 * maxSets);
|
poolbuilder.AddPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2 * maxSets);
|
||||||
if (fb->device->SupportsExtension(VK_KHR_RAY_QUERY_EXTENSION_NAME))
|
if (fb->device->SupportsExtension(VK_KHR_RAY_QUERY_EXTENSION_NAME))
|
||||||
|
{
|
||||||
poolbuilder.AddPoolSize(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 1 * maxSets);
|
poolbuilder.AddPoolSize(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 1 * maxSets);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
poolbuilder.AddPoolSize(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 3 * maxSets);
|
||||||
|
}
|
||||||
poolbuilder.MaxSets(maxSets);
|
poolbuilder.MaxSets(maxSets);
|
||||||
poolbuilder.DebugName("VkDescriptorSetManager.FixedDescriptorPool");
|
poolbuilder.DebugName("VkDescriptorSetManager.FixedDescriptorPool");
|
||||||
FixedDescriptorPool = poolbuilder.Create(fb->device.get());
|
FixedDescriptorPool = poolbuilder.Create(fb->device.get());
|
||||||
|
|
|
@ -28,6 +28,8 @@
|
||||||
|
|
||||||
VkRaytrace::VkRaytrace(VulkanRenderDevice* fb) : fb(fb)
|
VkRaytrace::VkRaytrace(VulkanRenderDevice* fb) : fb(fb)
|
||||||
{
|
{
|
||||||
|
useRayQuery = fb->device->SupportsExtension(VK_KHR_RAY_QUERY_EXTENSION_NAME);
|
||||||
|
|
||||||
NullMesh.MeshVertices.Push({ -1.0f, -1.0f, -1.0f });
|
NullMesh.MeshVertices.Push({ -1.0f, -1.0f, -1.0f });
|
||||||
NullMesh.MeshVertices.Push({ 1.0f, -1.0f, -1.0f });
|
NullMesh.MeshVertices.Push({ 1.0f, -1.0f, -1.0f });
|
||||||
NullMesh.MeshVertices.Push({ 1.0f, 1.0f, -1.0f });
|
NullMesh.MeshVertices.Push({ 1.0f, 1.0f, -1.0f });
|
||||||
|
@ -43,6 +45,8 @@ VkRaytrace::VkRaytrace(VulkanRenderDevice* fb) : fb(fb)
|
||||||
for (int i = 0; i < 3 * 4; i++)
|
for (int i = 0; i < 3 * 4; i++)
|
||||||
NullMesh.MeshElements.Push(i);
|
NullMesh.MeshElements.Push(i);
|
||||||
|
|
||||||
|
NullMesh.Collision = std::make_unique<TriangleMeshShape>(NullMesh.MeshVertices.Data(), NullMesh.MeshVertices.Size(), NullMesh.MeshElements.Data(), NullMesh.MeshElements.Size());
|
||||||
|
|
||||||
SetLevelMesh(nullptr);
|
SetLevelMesh(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,10 +59,7 @@ void VkRaytrace::SetLevelMesh(hwrenderer::LevelMesh* mesh)
|
||||||
{
|
{
|
||||||
Reset();
|
Reset();
|
||||||
Mesh = mesh;
|
Mesh = mesh;
|
||||||
if (fb->device->SupportsExtension(VK_KHR_RAY_QUERY_EXTENSION_NAME))
|
CreateVulkanObjects();
|
||||||
{
|
|
||||||
CreateVulkanObjects();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,6 +69,7 @@ void VkRaytrace::Reset()
|
||||||
deletelist->Add(std::move(vertexBuffer));
|
deletelist->Add(std::move(vertexBuffer));
|
||||||
deletelist->Add(std::move(indexBuffer));
|
deletelist->Add(std::move(indexBuffer));
|
||||||
deletelist->Add(std::move(transferBuffer));
|
deletelist->Add(std::move(transferBuffer));
|
||||||
|
deletelist->Add(std::move(nodesBuffer));
|
||||||
deletelist->Add(std::move(blScratchBuffer));
|
deletelist->Add(std::move(blScratchBuffer));
|
||||||
deletelist->Add(std::move(blAccelStructBuffer));
|
deletelist->Add(std::move(blAccelStructBuffer));
|
||||||
deletelist->Add(std::move(blAccelStruct));
|
deletelist->Add(std::move(blAccelStruct));
|
||||||
|
@ -81,38 +83,35 @@ void VkRaytrace::Reset()
|
||||||
void VkRaytrace::CreateVulkanObjects()
|
void VkRaytrace::CreateVulkanObjects()
|
||||||
{
|
{
|
||||||
CreateVertexAndIndexBuffers();
|
CreateVertexAndIndexBuffers();
|
||||||
CreateBottomLevelAccelerationStructure();
|
if (useRayQuery)
|
||||||
CreateTopLevelAccelerationStructure();
|
{
|
||||||
|
CreateBottomLevelAccelerationStructure();
|
||||||
|
CreateTopLevelAccelerationStructure();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VkRaytrace::CreateVertexAndIndexBuffers()
|
void VkRaytrace::CreateVertexAndIndexBuffers()
|
||||||
{
|
{
|
||||||
static_assert(sizeof(FVector3) == 3 * 4, "sizeof(FVector3) is not 12 bytes!");
|
std::vector<CollisionNode> nodes = CreateCollisionNodes();
|
||||||
|
|
||||||
size_t vertexbuffersize = (size_t)Mesh->MeshVertices.Size() * sizeof(FVector3);
|
// std430 alignment rules forces us to convert the vec3 to a vec4
|
||||||
size_t indexbuffersize = (size_t)Mesh->MeshElements.Size() * sizeof(uint32_t);
|
std::vector<FVector4> vertices;
|
||||||
size_t transferbuffersize = vertexbuffersize + indexbuffersize;
|
vertices.reserve(Mesh->MeshVertices.Size());
|
||||||
size_t vertexoffset = 0;
|
for (const FVector3& v : Mesh->MeshVertices)
|
||||||
size_t indexoffset = vertexoffset + vertexbuffersize;
|
vertices.push_back({ v, 1.0f });
|
||||||
|
|
||||||
transferBuffer = BufferBuilder()
|
CollisionNodeBufferHeader nodesHeader;
|
||||||
.Usage(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY)
|
nodesHeader.root = Mesh->Collision->get_root();
|
||||||
.Size(transferbuffersize)
|
|
||||||
.DebugName("transferBuffer")
|
|
||||||
.Create(fb->device.get());
|
|
||||||
|
|
||||||
uint8_t* data = (uint8_t*)transferBuffer->Map(0, transferbuffersize);
|
|
||||||
memcpy(data + vertexoffset, Mesh->MeshVertices.Data(), vertexbuffersize);
|
|
||||||
memcpy(data + indexoffset, Mesh->MeshElements.Data(), indexbuffersize);
|
|
||||||
transferBuffer->Unmap();
|
|
||||||
|
|
||||||
vertexBuffer = BufferBuilder()
|
vertexBuffer = BufferBuilder()
|
||||||
.Usage(
|
.Usage(
|
||||||
VK_BUFFER_USAGE_VERTEX_BUFFER_BIT |
|
VK_BUFFER_USAGE_VERTEX_BUFFER_BIT |
|
||||||
VK_BUFFER_USAGE_TRANSFER_DST_BIT |
|
VK_BUFFER_USAGE_TRANSFER_DST_BIT |
|
||||||
VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT |
|
(useRayQuery ?
|
||||||
VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR)
|
VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT |
|
||||||
.Size(vertexbuffersize)
|
VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR : 0) |
|
||||||
|
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT)
|
||||||
|
.Size(vertices.size() * sizeof(FVector4))
|
||||||
.DebugName("vertexBuffer")
|
.DebugName("vertexBuffer")
|
||||||
.Create(fb->device.get());
|
.Create(fb->device.get());
|
||||||
|
|
||||||
|
@ -120,19 +119,29 @@ void VkRaytrace::CreateVertexAndIndexBuffers()
|
||||||
.Usage(
|
.Usage(
|
||||||
VK_BUFFER_USAGE_INDEX_BUFFER_BIT |
|
VK_BUFFER_USAGE_INDEX_BUFFER_BIT |
|
||||||
VK_BUFFER_USAGE_TRANSFER_DST_BIT |
|
VK_BUFFER_USAGE_TRANSFER_DST_BIT |
|
||||||
VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT |
|
(useRayQuery ?
|
||||||
VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR)
|
VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT |
|
||||||
.Size(indexbuffersize)
|
VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR : 0) |
|
||||||
|
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT)
|
||||||
|
.Size((size_t)Mesh->MeshElements.Size() * sizeof(uint32_t))
|
||||||
.DebugName("indexBuffer")
|
.DebugName("indexBuffer")
|
||||||
.Create(fb->device.get());
|
.Create(fb->device.get());
|
||||||
|
|
||||||
fb->GetCommands()->GetTransferCommands()->copyBuffer(transferBuffer.get(), vertexBuffer.get(), vertexoffset);
|
nodesBuffer = BufferBuilder()
|
||||||
fb->GetCommands()->GetTransferCommands()->copyBuffer(transferBuffer.get(), indexBuffer.get(), indexoffset);
|
.Usage(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT)
|
||||||
|
.Size(sizeof(CollisionNodeBufferHeader) + nodes.size() * sizeof(CollisionNode))
|
||||||
|
.DebugName("nodesBuffer")
|
||||||
|
.Create(fb->device.get());
|
||||||
|
|
||||||
|
transferBuffer = BufferTransfer()
|
||||||
|
.AddBuffer(vertexBuffer.get(), vertices.data(), vertices.size() * sizeof(FVector4))
|
||||||
|
.AddBuffer(indexBuffer.get(), Mesh->MeshElements.Data(), (size_t)Mesh->MeshElements.Size() * sizeof(uint32_t))
|
||||||
|
.AddBuffer(nodesBuffer.get(), &nodesHeader, sizeof(CollisionNodeBufferHeader), nodes.data(), nodes.size() * sizeof(CollisionNode))
|
||||||
|
.Execute(fb->device.get(), fb->GetCommands()->GetTransferCommands());
|
||||||
|
|
||||||
// Finish transfer before using it for building
|
|
||||||
PipelineBarrier()
|
PipelineBarrier()
|
||||||
.AddMemory(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT)
|
.AddMemory(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT)
|
||||||
.Execute(fb->GetCommands()->GetTransferCommands(), VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR);
|
.Execute(fb->GetCommands()->GetTransferCommands(), VK_PIPELINE_STAGE_TRANSFER_BIT, useRayQuery ? VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR : VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VkRaytrace::CreateBottomLevelAccelerationStructure()
|
void VkRaytrace::CreateBottomLevelAccelerationStructure()
|
||||||
|
@ -146,9 +155,9 @@ void VkRaytrace::CreateBottomLevelAccelerationStructure()
|
||||||
accelStructBLDesc.geometryType = VK_GEOMETRY_TYPE_TRIANGLES_KHR;
|
accelStructBLDesc.geometryType = VK_GEOMETRY_TYPE_TRIANGLES_KHR;
|
||||||
accelStructBLDesc.flags = VK_GEOMETRY_OPAQUE_BIT_KHR;
|
accelStructBLDesc.flags = VK_GEOMETRY_OPAQUE_BIT_KHR;
|
||||||
accelStructBLDesc.geometry.triangles = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR };
|
accelStructBLDesc.geometry.triangles = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR };
|
||||||
accelStructBLDesc.geometry.triangles.vertexFormat = VK_FORMAT_R32G32B32_SFLOAT;
|
accelStructBLDesc.geometry.triangles.vertexFormat = VK_FORMAT_R32G32B32A32_SFLOAT;
|
||||||
accelStructBLDesc.geometry.triangles.vertexData.deviceAddress = vertexBuffer->GetDeviceAddress();
|
accelStructBLDesc.geometry.triangles.vertexData.deviceAddress = vertexBuffer->GetDeviceAddress();
|
||||||
accelStructBLDesc.geometry.triangles.vertexStride = sizeof(FVector3);
|
accelStructBLDesc.geometry.triangles.vertexStride = sizeof(FVector4);
|
||||||
accelStructBLDesc.geometry.triangles.indexType = VK_INDEX_TYPE_UINT32;
|
accelStructBLDesc.geometry.triangles.indexType = VK_INDEX_TYPE_UINT32;
|
||||||
accelStructBLDesc.geometry.triangles.indexData.deviceAddress = indexBuffer->GetDeviceAddress();
|
accelStructBLDesc.geometry.triangles.indexData.deviceAddress = indexBuffer->GetDeviceAddress();
|
||||||
accelStructBLDesc.geometry.triangles.maxVertex = Mesh->MeshVertices.Size() - 1;
|
accelStructBLDesc.geometry.triangles.maxVertex = Mesh->MeshVertices.Size() - 1;
|
||||||
|
@ -277,3 +286,78 @@ void VkRaytrace::CreateTopLevelAccelerationStructure()
|
||||||
.AddMemory(VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR, VK_ACCESS_SHADER_READ_BIT)
|
.AddMemory(VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR, VK_ACCESS_SHADER_READ_BIT)
|
||||||
.Execute(fb->GetCommands()->GetTransferCommands(), VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
|
.Execute(fb->GetCommands()->GetTransferCommands(), VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<CollisionNode> VkRaytrace::CreateCollisionNodes()
|
||||||
|
{
|
||||||
|
std::vector<CollisionNode> nodes;
|
||||||
|
nodes.reserve(Mesh->Collision->get_nodes().size());
|
||||||
|
for (const auto& node : Mesh->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_back(info);
|
||||||
|
}
|
||||||
|
if (nodes.empty()) // vulkan doesn't support zero byte buffers
|
||||||
|
nodes.push_back(CollisionNode());
|
||||||
|
return nodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
BufferTransfer& BufferTransfer::AddBuffer(VulkanBuffer* buffer, const void* data, size_t size)
|
||||||
|
{
|
||||||
|
bufferCopies.push_back({ buffer, 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, 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, 0, copy.size0);
|
||||||
|
pos += copy.size0;
|
||||||
|
|
||||||
|
if (copy.size1 > 0)
|
||||||
|
cmdbuffer->copyBuffer(transferBuffer.get(), copy.buffer, pos, copy.size0, copy.size1);
|
||||||
|
pos += copy.size1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return transferBuffer;
|
||||||
|
}
|
||||||
|
|
|
@ -6,6 +6,26 @@
|
||||||
|
|
||||||
class VulkanRenderDevice;
|
class VulkanRenderDevice;
|
||||||
|
|
||||||
|
struct CollisionNodeBufferHeader
|
||||||
|
{
|
||||||
|
int root;
|
||||||
|
int padding1;
|
||||||
|
int padding2;
|
||||||
|
int padding3;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CollisionNode
|
||||||
|
{
|
||||||
|
FVector3 center;
|
||||||
|
float padding1;
|
||||||
|
FVector3 extents;
|
||||||
|
float padding2;
|
||||||
|
int left;
|
||||||
|
int right;
|
||||||
|
int element_index;
|
||||||
|
int padding3;
|
||||||
|
};
|
||||||
|
|
||||||
class VkRaytrace
|
class VkRaytrace
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -14,6 +34,9 @@ public:
|
||||||
void SetLevelMesh(hwrenderer::LevelMesh* mesh);
|
void SetLevelMesh(hwrenderer::LevelMesh* mesh);
|
||||||
|
|
||||||
VulkanAccelerationStructure* GetAccelStruct() { return tlAccelStruct.get(); }
|
VulkanAccelerationStructure* GetAccelStruct() { return tlAccelStruct.get(); }
|
||||||
|
VulkanBuffer* GetVertexBuffer() { return vertexBuffer.get(); }
|
||||||
|
VulkanBuffer* GetIndexBuffer() { return indexBuffer.get(); }
|
||||||
|
VulkanBuffer* GetNodeBuffer() { return nodesBuffer.get(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void Reset();
|
void Reset();
|
||||||
|
@ -22,14 +45,19 @@ private:
|
||||||
void CreateBottomLevelAccelerationStructure();
|
void CreateBottomLevelAccelerationStructure();
|
||||||
void CreateTopLevelAccelerationStructure();
|
void CreateTopLevelAccelerationStructure();
|
||||||
|
|
||||||
|
std::vector<CollisionNode> CreateCollisionNodes();
|
||||||
|
|
||||||
VulkanRenderDevice* fb = nullptr;
|
VulkanRenderDevice* fb = nullptr;
|
||||||
|
|
||||||
|
bool useRayQuery = true;
|
||||||
|
|
||||||
hwrenderer::LevelMesh NullMesh;
|
hwrenderer::LevelMesh NullMesh;
|
||||||
hwrenderer::LevelMesh* Mesh = nullptr;
|
hwrenderer::LevelMesh* Mesh = nullptr;
|
||||||
|
|
||||||
std::unique_ptr<VulkanBuffer> vertexBuffer;
|
std::unique_ptr<VulkanBuffer> vertexBuffer;
|
||||||
std::unique_ptr<VulkanBuffer> indexBuffer;
|
std::unique_ptr<VulkanBuffer> indexBuffer;
|
||||||
std::unique_ptr<VulkanBuffer> transferBuffer;
|
std::unique_ptr<VulkanBuffer> transferBuffer;
|
||||||
|
std::unique_ptr<VulkanBuffer> nodesBuffer;
|
||||||
|
|
||||||
std::unique_ptr<VulkanBuffer> blScratchBuffer;
|
std::unique_ptr<VulkanBuffer> blScratchBuffer;
|
||||||
std::unique_ptr<VulkanBuffer> blAccelStructBuffer;
|
std::unique_ptr<VulkanBuffer> blAccelStructBuffer;
|
||||||
|
@ -41,3 +69,22 @@ private:
|
||||||
std::unique_ptr<VulkanBuffer> tlAccelStructBuffer;
|
std::unique_ptr<VulkanBuffer> tlAccelStructBuffer;
|
||||||
std::unique_ptr<VulkanAccelerationStructure> tlAccelStruct;
|
std::unique_ptr<VulkanAccelerationStructure> tlAccelStruct;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class BufferTransfer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
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;
|
||||||
|
const void* data0;
|
||||||
|
size_t size0;
|
||||||
|
const void* data1;
|
||||||
|
size_t size1;
|
||||||
|
};
|
||||||
|
std::vector<BufferCopy> bufferCopies;
|
||||||
|
};
|
||||||
|
|
|
@ -1,8 +1,32 @@
|
||||||
|
|
||||||
layout(set = 0, binding = 0) uniform sampler2D ShadowMap;
|
layout(set = 0, binding = 0) uniform sampler2D ShadowMap;
|
||||||
layout(set = 0, binding = 1) uniform sampler2DArray LightMap;
|
layout(set = 0, binding = 1) uniform sampler2DArray LightMap;
|
||||||
#if defined(USE_RAYTRACE) && defined(SUPPORTS_RAYQUERY)
|
#if defined(USE_RAYTRACE)
|
||||||
|
#if defined(SUPPORTS_RAYQUERY)
|
||||||
layout(set = 0, binding = 2) uniform accelerationStructureEXT TopLevelAS;
|
layout(set = 0, binding = 2) uniform accelerationStructureEXT TopLevelAS;
|
||||||
|
#else
|
||||||
|
struct CollisionNode
|
||||||
|
{
|
||||||
|
vec3 center;
|
||||||
|
float padding1;
|
||||||
|
vec3 extents;
|
||||||
|
float padding2;
|
||||||
|
int left;
|
||||||
|
int right;
|
||||||
|
int element_index;
|
||||||
|
int padding3;
|
||||||
|
};
|
||||||
|
layout(std430, set = 0, binding = 2) buffer NodeBuffer
|
||||||
|
{
|
||||||
|
int nodesRoot;
|
||||||
|
int nodebufferPadding1;
|
||||||
|
int nodebufferPadding2;
|
||||||
|
int nodebufferPadding3;
|
||||||
|
CollisionNode nodes[];
|
||||||
|
};
|
||||||
|
layout(std430, set = 0, binding = 3) buffer VertexBuffer { vec4 vertices[]; };
|
||||||
|
layout(std430, set = 0, binding = 4) buffer ElementBuffer { int elements[]; };
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// This must match the HWViewpointUniforms struct
|
// This must match the HWViewpointUniforms struct
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
|
|
||||||
// Check if light is in shadow
|
// Check if light is in shadow
|
||||||
|
|
||||||
#if defined(USE_RAYTRACE) && defined(SUPPORTS_RAYQUERY)
|
#if defined(USE_RAYTRACE)
|
||||||
|
|
||||||
|
#if defined(SUPPORTS_RAYQUERY)
|
||||||
|
|
||||||
bool traceHit(vec3 origin, vec3 direction, float dist)
|
bool traceHit(vec3 origin, vec3 direction, float dist)
|
||||||
{
|
{
|
||||||
|
@ -11,6 +13,160 @@ bool traceHit(vec3 origin, vec3 direction, float dist)
|
||||||
return rayQueryGetIntersectionTypeEXT(rayQuery, true) != gl_RayQueryCommittedIntersectionNoneEXT;
|
return rayQueryGetIntersectionTypeEXT(rayQuery, true) != gl_RayQueryCommittedIntersectionNoneEXT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
struct RayBBox
|
||||||
|
{
|
||||||
|
vec3 start, end;
|
||||||
|
vec3 c, w, v;
|
||||||
|
};
|
||||||
|
|
||||||
|
RayBBox create_ray(vec3 ray_start, vec3 ray_end)
|
||||||
|
{
|
||||||
|
RayBBox ray;
|
||||||
|
ray.start = ray_start;
|
||||||
|
ray.end = ray_end;
|
||||||
|
ray.c = (ray_start + ray_end) * 0.5;
|
||||||
|
ray.w = ray_end - ray.c;
|
||||||
|
ray.v = abs(ray.w);
|
||||||
|
return ray;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool overlap_bv_ray(RayBBox ray, int a)
|
||||||
|
{
|
||||||
|
vec3 v = ray.v;
|
||||||
|
vec3 w = ray.w;
|
||||||
|
vec3 h = nodes[a].extents;
|
||||||
|
vec3 c = ray.c - nodes[a].center;
|
||||||
|
|
||||||
|
if (abs(c.x) > v.x + h.x ||
|
||||||
|
abs(c.y) > v.y + h.y ||
|
||||||
|
abs(c.z) > v.z + h.z)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (abs(c.y * w.z - c.z * w.y) > h.y * v.z + h.z * v.y ||
|
||||||
|
abs(c.x * w.z - c.z * w.x) > h.x * v.z + h.z * v.x ||
|
||||||
|
abs(c.x * w.y - c.y * w.x) > h.x * v.y + h.y * v.x)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define FLT_EPSILON 1.192092896e-07F // smallest such that 1.0+FLT_EPSILON != 1.0
|
||||||
|
|
||||||
|
float intersect_triangle_ray(RayBBox ray, int a, out float barycentricB, out float barycentricC)
|
||||||
|
{
|
||||||
|
int start_element = nodes[a].element_index;
|
||||||
|
|
||||||
|
vec3 p[3];
|
||||||
|
p[0] = vertices[elements[start_element]].xyz;
|
||||||
|
p[1] = vertices[elements[start_element + 1]].xyz;
|
||||||
|
p[2] = vertices[elements[start_element + 2]].xyz;
|
||||||
|
|
||||||
|
// Moeller-Trumbore ray-triangle intersection algorithm:
|
||||||
|
|
||||||
|
vec3 D = ray.end - ray.start;
|
||||||
|
|
||||||
|
// Find vectors for two edges sharing p[0]
|
||||||
|
vec3 e1 = p[1] - p[0];
|
||||||
|
vec3 e2 = p[2] - p[0];
|
||||||
|
|
||||||
|
// Begin calculating determinant - also used to calculate u parameter
|
||||||
|
vec3 P = cross(D, e2);
|
||||||
|
float det = dot(e1, P);
|
||||||
|
|
||||||
|
// Backface check
|
||||||
|
//if (det < 0.0f)
|
||||||
|
// return 1.0f;
|
||||||
|
|
||||||
|
// If determinant is near zero, ray lies in plane of triangle
|
||||||
|
if (det > -FLT_EPSILON && det < FLT_EPSILON)
|
||||||
|
return 1.0f;
|
||||||
|
|
||||||
|
float inv_det = 1.0f / det;
|
||||||
|
|
||||||
|
// Calculate distance from p[0] to ray origin
|
||||||
|
vec3 T = ray.start - p[0];
|
||||||
|
|
||||||
|
// Calculate u parameter and test bound
|
||||||
|
float u = dot(T, P) * inv_det;
|
||||||
|
|
||||||
|
// Check if the intersection lies outside of the triangle
|
||||||
|
if (u < 0.f || u > 1.f)
|
||||||
|
return 1.0f;
|
||||||
|
|
||||||
|
// Prepare to test v parameter
|
||||||
|
vec3 Q = cross(T, e1);
|
||||||
|
|
||||||
|
// Calculate V parameter and test bound
|
||||||
|
float v = dot(D, Q) * inv_det;
|
||||||
|
|
||||||
|
// The intersection lies outside of the triangle
|
||||||
|
if (v < 0.f || u + v > 1.f)
|
||||||
|
return 1.0f;
|
||||||
|
|
||||||
|
float t = dot(e2, Q) * inv_det;
|
||||||
|
if (t <= FLT_EPSILON)
|
||||||
|
return 1.0f;
|
||||||
|
|
||||||
|
// Return hit location on triangle in barycentric coordinates
|
||||||
|
barycentricB = u;
|
||||||
|
barycentricC = v;
|
||||||
|
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_leaf(int node_index)
|
||||||
|
{
|
||||||
|
return nodes[node_index].element_index != -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TraceAnyHit(vec3 origin, float tmin, vec3 dir, float tmax)
|
||||||
|
{
|
||||||
|
if (tmax <= 0.0f)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
RayBBox ray = create_ray(origin, origin + dir * tmax);
|
||||||
|
tmin /= tmax;
|
||||||
|
|
||||||
|
int stack[64];
|
||||||
|
int stackIndex = 0;
|
||||||
|
stack[stackIndex++] = nodesRoot;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
int a = stack[--stackIndex];
|
||||||
|
if (overlap_bv_ray(ray, a))
|
||||||
|
{
|
||||||
|
if (is_leaf(a))
|
||||||
|
{
|
||||||
|
float baryB, baryC;
|
||||||
|
float t = intersect_triangle_ray(ray, a, baryB, baryC);
|
||||||
|
if (t >= tmin && t < 1.0)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
stack[stackIndex++] = nodes[a].right;
|
||||||
|
stack[stackIndex++] = nodes[a].left;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (stackIndex > 0);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool traceHit(vec3 origin, vec3 direction, float dist)
|
||||||
|
{
|
||||||
|
return TraceAnyHit(origin, 0.01f, direction, dist);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
vec2 softshadow[9 * 3] = vec2[](
|
vec2 softshadow[9 * 3] = vec2[](
|
||||||
vec2( 0.0, 0.0),
|
vec2( 0.0, 0.0),
|
||||||
vec2(-2.0,-2.0),
|
vec2(-2.0,-2.0),
|
||||||
|
|
Loading…
Reference in a new issue