mirror of
https://github.com/ZDoom/ZDRay.git
synced 2024-11-21 19:50:54 +00:00
Clean up some code by moving it into functions
This commit is contained in:
parent
66124477b2
commit
59c58b75f1
2 changed files with 251 additions and 220 deletions
|
@ -43,202 +43,19 @@ void GPURaytracer2::Raytrace(LevelMesh* level)
|
|||
|
||||
printf("Ray tracing in progress...\n");
|
||||
|
||||
CreateAtlasImages();
|
||||
|
||||
BeginCommands();
|
||||
UploadUniforms();
|
||||
|
||||
Uniforms2 uniforms = {};
|
||||
uniforms.SunDir = mesh->map->GetSunDirection();
|
||||
uniforms.SunColor = mesh->map->GetSunColor();
|
||||
uniforms.SunIntensity = 1.0f;
|
||||
|
||||
mappedUniforms = (uint8_t*)uniformTransferBuffer->Map(0, uniformStructs * uniformStructStride);
|
||||
*reinterpret_cast<Uniforms2*>(mappedUniforms + uniformStructStride * uniformsIndex) = uniforms;
|
||||
uniformTransferBuffer->Unmap();
|
||||
|
||||
cmdbuffer->copyBuffer(uniformTransferBuffer.get(), uniformBuffer.get());
|
||||
PipelineBarrier()
|
||||
.AddBuffer(uniformBuffer.get(), VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT)
|
||||
.Execute(cmdbuffer.get(), VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
|
||||
|
||||
const int atlasImageSize = 2048;
|
||||
const int spacing = 3; // Note: the spacing is here to avoid that the resolve sampler finds data from other surface tiles
|
||||
RectPacker packer(atlasImageSize, atlasImageSize, RectPacker::Spacing(spacing));
|
||||
|
||||
for (size_t i = 0; i < mesh->surfaces.size(); i++)
|
||||
for (size_t pageIndex = 0; pageIndex < atlasImages.size(); pageIndex++)
|
||||
{
|
||||
Surface* surface = mesh->surfaces[i].get();
|
||||
|
||||
auto result = packer.insert(surface->texWidth + 2, surface->texHeight + 2);
|
||||
surface->atlasX = result.pos.x + 1;
|
||||
surface->atlasY = result.pos.y + 1;
|
||||
surface->atlasPageIndex = (int)result.pageIndex;
|
||||
}
|
||||
|
||||
std::vector<LightmapImage> atlasImages;
|
||||
for (size_t pageIndex = 0; pageIndex < packer.getNumPages(); pageIndex++)
|
||||
{
|
||||
atlasImages.push_back(CreateImage(atlasImageSize, atlasImageSize));
|
||||
RenderAtlasImage(pageIndex);
|
||||
}
|
||||
|
||||
for (size_t pageIndex = 0; pageIndex < atlasImages.size(); pageIndex++)
|
||||
{
|
||||
LightmapImage& img = atlasImages[pageIndex];
|
||||
|
||||
RenderPassBegin()
|
||||
.RenderPass(raytrace.renderPass.get())
|
||||
.RenderArea(0, 0, atlasImageSize, atlasImageSize)
|
||||
.Framebuffer(img.raytrace.Framebuffer.get())
|
||||
.Execute(cmdbuffer.get());
|
||||
|
||||
VkDeviceSize offset = 0;
|
||||
cmdbuffer->bindVertexBuffers(0, 1, &sceneVertexBuffer->buffer, &offset);
|
||||
cmdbuffer->bindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, raytrace.pipeline.get());
|
||||
cmdbuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, raytrace.pipelineLayout.get(), 0, raytrace.descriptorSet.get());
|
||||
|
||||
for (size_t i = 0; i < mesh->surfaces.size(); i++)
|
||||
{
|
||||
Surface* targetSurface = mesh->surfaces[i].get();
|
||||
if (targetSurface->atlasPageIndex != pageIndex)
|
||||
continue;
|
||||
|
||||
VkViewport viewport = {};
|
||||
viewport.maxDepth = 1;
|
||||
viewport.x = (float)targetSurface->atlasX - 1;
|
||||
viewport.y = (float)targetSurface->atlasY - 1;
|
||||
viewport.width = (float)(targetSurface->texWidth + 2);
|
||||
viewport.height = (float)(targetSurface->texHeight + 2);
|
||||
cmdbuffer->setViewport(0, 1, &viewport);
|
||||
|
||||
// Paint all surfaces part of the smoothing group into the surface
|
||||
for (const auto& surface : mesh->surfaces)
|
||||
{
|
||||
if (surface->smoothingGroupIndex != targetSurface->smoothingGroupIndex)
|
||||
continue;
|
||||
|
||||
vec2 minUV = ToUV(surface->bounds.min, targetSurface);
|
||||
vec2 maxUV = ToUV(surface->bounds.max, targetSurface);
|
||||
if (surface.get() != targetSurface && (maxUV.x < 0.0f || maxUV.y < 0.0f || minUV.x > 1.0f || minUV.y > 1.0f))
|
||||
continue; // Bounding box not visible
|
||||
|
||||
int firstLight = sceneLightPos;
|
||||
int lightCount = (int)surface->LightList.size();
|
||||
if (sceneLightPos + lightCount > SceneLightBufferSize)
|
||||
throw std::runtime_error("SceneLightBuffer is too small!");
|
||||
sceneLightPos += lightCount;
|
||||
|
||||
LightInfo2* lightinfo = &sceneLights[firstLight];
|
||||
for (ThingLight* light : surface->LightList)
|
||||
{
|
||||
lightinfo->Origin = light->LightOrigin();
|
||||
lightinfo->Radius = light->LightRadius();
|
||||
lightinfo->Intensity = light->intensity;
|
||||
lightinfo->InnerAngleCos = light->innerAngleCos;
|
||||
lightinfo->OuterAngleCos = light->outerAngleCos;
|
||||
lightinfo->SpotDir = light->SpotDir();
|
||||
lightinfo->Color = light->rgb;
|
||||
lightinfo++;
|
||||
}
|
||||
|
||||
PushConstants2 pc;
|
||||
pc.LightStart = firstLight;
|
||||
pc.LightEnd = firstLight + lightCount;
|
||||
pc.SurfaceIndex = (int32_t)i;
|
||||
pc.LightmapOrigin = targetSurface->worldOrigin - targetSurface->worldStepX - targetSurface->worldStepY;
|
||||
pc.LightmapStepX = targetSurface->worldStepX * viewport.width;
|
||||
pc.LightmapStepY = targetSurface->worldStepY * viewport.height;
|
||||
cmdbuffer->pushConstants(raytrace.pipelineLayout.get(), VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(PushConstants2), &pc);
|
||||
|
||||
int firstVertex = sceneVertexPos;
|
||||
int vertexCount = (int)surface->verts.size();
|
||||
if (sceneVertexPos + vertexCount > SceneVertexBufferSize)
|
||||
throw std::runtime_error("SceneVertexBuffer is too small!");
|
||||
sceneVertexPos += vertexCount;
|
||||
SceneVertex* vertex = &sceneVertices[firstVertex];
|
||||
|
||||
if (surface->type == ST_FLOOR || surface->type == ST_CEILING)
|
||||
{
|
||||
for (int idx = 0; idx < vertexCount; idx++)
|
||||
{
|
||||
(vertex++)->Position = ToUV(surface->verts[idx], targetSurface);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
(vertex++)->Position = ToUV(surface->verts[0], targetSurface);
|
||||
(vertex++)->Position = ToUV(surface->verts[2], targetSurface);
|
||||
(vertex++)->Position = ToUV(surface->verts[3], targetSurface);
|
||||
(vertex++)->Position = ToUV(surface->verts[1], targetSurface);
|
||||
}
|
||||
|
||||
cmdbuffer->draw(vertexCount, 1, firstVertex, 0);
|
||||
}
|
||||
}
|
||||
cmdbuffer->endRenderPass();
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < atlasImages.size(); i++)
|
||||
{
|
||||
LightmapImage& img = atlasImages[i];
|
||||
|
||||
PipelineBarrier()
|
||||
.AddImage(img.raytrace.Image.get(), VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT)
|
||||
.Execute(cmdbuffer.get(), VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
|
||||
|
||||
RenderPassBegin()
|
||||
.RenderPass(resolve.renderPass.get())
|
||||
.RenderArea(0, 0, atlasImageSize, atlasImageSize)
|
||||
.Framebuffer(img.resolve.Framebuffer.get())
|
||||
.Execute(cmdbuffer.get());
|
||||
|
||||
VkDeviceSize offset = 0;
|
||||
cmdbuffer->bindVertexBuffers(0, 1, &sceneVertexBuffer->buffer, &offset);
|
||||
cmdbuffer->bindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, resolve.pipeline.get());
|
||||
|
||||
auto descriptorSet = resolve.descriptorPool->allocate(resolve.descriptorSetLayout.get());
|
||||
descriptorSet->SetDebugName("resolve.descriptorSet");
|
||||
WriteDescriptors()
|
||||
.AddCombinedImageSampler(descriptorSet.get(), 0, img.raytrace.View.get(), resolve.sampler.get(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
|
||||
.Execute(device.get());
|
||||
cmdbuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, resolve.pipelineLayout.get(), 0, descriptorSet.get());
|
||||
resolve.descriptorSets.push_back(std::move(descriptorSet));
|
||||
|
||||
VkViewport viewport = {};
|
||||
viewport.maxDepth = 1;
|
||||
viewport.width = (float)atlasImageSize;
|
||||
viewport.height = (float)atlasImageSize;
|
||||
cmdbuffer->setViewport(0, 1, &viewport);
|
||||
|
||||
PushConstants2 pc;
|
||||
pc.LightStart = 0;
|
||||
pc.LightEnd = 0;
|
||||
pc.SurfaceIndex = 0;
|
||||
pc.LightmapOrigin = vec3(0.0f);
|
||||
pc.LightmapStepX = vec3(0.0f);
|
||||
pc.LightmapStepY = vec3(0.0f);
|
||||
cmdbuffer->pushConstants(resolve.pipelineLayout.get(), VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(PushConstants2), &pc);
|
||||
|
||||
int firstVertex = sceneVertexPos;
|
||||
int vertexCount = 4;
|
||||
sceneVertexPos += vertexCount;
|
||||
SceneVertex* vertex = &sceneVertices[firstVertex];
|
||||
vertex[0].Position = vec2(0.0f, 0.0f);
|
||||
vertex[1].Position = vec2(1.0f, 0.0f);
|
||||
vertex[2].Position = vec2(1.0f, 1.0f);
|
||||
vertex[3].Position = vec2(0.0f, 1.0f);
|
||||
cmdbuffer->draw(vertexCount, 1, firstVertex, 0);
|
||||
|
||||
cmdbuffer->endRenderPass();
|
||||
|
||||
PipelineBarrier()
|
||||
.AddImage(img.resolve.Image.get(), VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT)
|
||||
.Execute(cmdbuffer.get(), VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
|
||||
|
||||
VkBufferImageCopy region = {};
|
||||
region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
region.imageSubresource.layerCount = 1;
|
||||
region.imageExtent.width = atlasImageSize;
|
||||
region.imageExtent.height = atlasImageSize;
|
||||
region.imageExtent.depth = 1;
|
||||
cmdbuffer->copyImageToBuffer(img.resolve.Image->image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, img.Transfer->buffer, 1, ®ion);
|
||||
ResolveAtlasImage(pageIndex);
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
|
@ -255,39 +72,9 @@ void GPURaytracer2::Raytrace(LevelMesh* level)
|
|||
printf("GPU ray tracing time was %.3f seconds.\n", double(e.QuadPart - s.QuadPart) / double(f.QuadPart));
|
||||
#endif
|
||||
|
||||
struct hvec4
|
||||
{
|
||||
unsigned short x,y,z,w;
|
||||
vec3 xyz() { return vec3(halfToFloat(x), halfToFloat(y), halfToFloat(z)); }
|
||||
};
|
||||
|
||||
for (size_t pageIndex = 0; pageIndex < atlasImages.size(); pageIndex++)
|
||||
{
|
||||
hvec4* pixels = (hvec4*)atlasImages[pageIndex].Transfer->Map(0, atlasImageSize * atlasImageSize * sizeof(hvec4));
|
||||
|
||||
for (size_t i = 0; i < mesh->surfaces.size(); i++)
|
||||
{
|
||||
Surface* surface = mesh->surfaces[i].get();
|
||||
if (surface->atlasPageIndex != pageIndex)
|
||||
continue;
|
||||
|
||||
int atlasX = surface->atlasX;
|
||||
int atlasY = surface->atlasY;
|
||||
int sampleWidth = surface->texWidth;
|
||||
int sampleHeight = surface->texHeight;
|
||||
|
||||
// Download
|
||||
for (int y = 0; y < sampleHeight; y++)
|
||||
{
|
||||
vec3* dest = &surface->texPixels[y * sampleWidth];
|
||||
hvec4* src = &pixels[atlasX + (atlasY + y) * atlasImageSize];
|
||||
for (int x = 0; x < sampleWidth; x++)
|
||||
{
|
||||
dest[x] = src[x].xyz();
|
||||
}
|
||||
}
|
||||
}
|
||||
atlasImages[pageIndex].Transfer->Unmap();
|
||||
DownloadAtlasImage(pageIndex);
|
||||
}
|
||||
|
||||
if (device->renderdoc)
|
||||
|
@ -296,6 +83,241 @@ void GPURaytracer2::Raytrace(LevelMesh* level)
|
|||
printf("Ray trace complete\n");
|
||||
}
|
||||
|
||||
void GPURaytracer2::RenderAtlasImage(size_t pageIndex)
|
||||
{
|
||||
LightmapImage& img = atlasImages[pageIndex];
|
||||
|
||||
RenderPassBegin()
|
||||
.RenderPass(raytrace.renderPass.get())
|
||||
.RenderArea(0, 0, atlasImageSize, atlasImageSize)
|
||||
.Framebuffer(img.raytrace.Framebuffer.get())
|
||||
.Execute(cmdbuffer.get());
|
||||
|
||||
VkDeviceSize offset = 0;
|
||||
cmdbuffer->bindVertexBuffers(0, 1, &sceneVertexBuffer->buffer, &offset);
|
||||
cmdbuffer->bindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, raytrace.pipeline.get());
|
||||
cmdbuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, raytrace.pipelineLayout.get(), 0, raytrace.descriptorSet.get());
|
||||
|
||||
for (size_t i = 0; i < mesh->surfaces.size(); i++)
|
||||
{
|
||||
Surface* targetSurface = mesh->surfaces[i].get();
|
||||
if (targetSurface->atlasPageIndex != pageIndex)
|
||||
continue;
|
||||
|
||||
VkViewport viewport = {};
|
||||
viewport.maxDepth = 1;
|
||||
viewport.x = (float)targetSurface->atlasX - 1;
|
||||
viewport.y = (float)targetSurface->atlasY - 1;
|
||||
viewport.width = (float)(targetSurface->texWidth + 2);
|
||||
viewport.height = (float)(targetSurface->texHeight + 2);
|
||||
cmdbuffer->setViewport(0, 1, &viewport);
|
||||
|
||||
// Paint all surfaces part of the smoothing group into the surface
|
||||
for (const auto& surface : mesh->surfaces)
|
||||
{
|
||||
if (surface->smoothingGroupIndex != targetSurface->smoothingGroupIndex)
|
||||
continue;
|
||||
|
||||
vec2 minUV = ToUV(surface->bounds.min, targetSurface);
|
||||
vec2 maxUV = ToUV(surface->bounds.max, targetSurface);
|
||||
if (surface.get() != targetSurface && (maxUV.x < 0.0f || maxUV.y < 0.0f || minUV.x > 1.0f || minUV.y > 1.0f))
|
||||
continue; // Bounding box not visible
|
||||
|
||||
int firstLight = sceneLightPos;
|
||||
int lightCount = (int)surface->LightList.size();
|
||||
if (sceneLightPos + lightCount > SceneLightBufferSize)
|
||||
throw std::runtime_error("SceneLightBuffer is too small!");
|
||||
sceneLightPos += lightCount;
|
||||
|
||||
LightInfo2* lightinfo = &sceneLights[firstLight];
|
||||
for (ThingLight* light : surface->LightList)
|
||||
{
|
||||
lightinfo->Origin = light->LightOrigin();
|
||||
lightinfo->Radius = light->LightRadius();
|
||||
lightinfo->Intensity = light->intensity;
|
||||
lightinfo->InnerAngleCos = light->innerAngleCos;
|
||||
lightinfo->OuterAngleCos = light->outerAngleCos;
|
||||
lightinfo->SpotDir = light->SpotDir();
|
||||
lightinfo->Color = light->rgb;
|
||||
lightinfo++;
|
||||
}
|
||||
|
||||
PushConstants2 pc;
|
||||
pc.LightStart = firstLight;
|
||||
pc.LightEnd = firstLight + lightCount;
|
||||
pc.SurfaceIndex = (int32_t)i;
|
||||
pc.LightmapOrigin = targetSurface->worldOrigin - targetSurface->worldStepX - targetSurface->worldStepY;
|
||||
pc.LightmapStepX = targetSurface->worldStepX * viewport.width;
|
||||
pc.LightmapStepY = targetSurface->worldStepY * viewport.height;
|
||||
cmdbuffer->pushConstants(raytrace.pipelineLayout.get(), VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(PushConstants2), &pc);
|
||||
|
||||
int firstVertex = sceneVertexPos;
|
||||
int vertexCount = (int)surface->verts.size();
|
||||
if (sceneVertexPos + vertexCount > SceneVertexBufferSize)
|
||||
throw std::runtime_error("SceneVertexBuffer is too small!");
|
||||
sceneVertexPos += vertexCount;
|
||||
SceneVertex* vertex = &sceneVertices[firstVertex];
|
||||
|
||||
if (surface->type == ST_FLOOR || surface->type == ST_CEILING)
|
||||
{
|
||||
for (int idx = 0; idx < vertexCount; idx++)
|
||||
{
|
||||
(vertex++)->Position = ToUV(surface->verts[idx], targetSurface);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
(vertex++)->Position = ToUV(surface->verts[0], targetSurface);
|
||||
(vertex++)->Position = ToUV(surface->verts[2], targetSurface);
|
||||
(vertex++)->Position = ToUV(surface->verts[3], targetSurface);
|
||||
(vertex++)->Position = ToUV(surface->verts[1], targetSurface);
|
||||
}
|
||||
|
||||
cmdbuffer->draw(vertexCount, 1, firstVertex, 0);
|
||||
}
|
||||
}
|
||||
|
||||
cmdbuffer->endRenderPass();
|
||||
}
|
||||
|
||||
void GPURaytracer2::CreateAtlasImages()
|
||||
{
|
||||
const int spacing = 3; // Note: the spacing is here to avoid that the resolve sampler finds data from other surface tiles
|
||||
RectPacker packer(atlasImageSize, atlasImageSize, RectPacker::Spacing(spacing));
|
||||
|
||||
for (size_t i = 0; i < mesh->surfaces.size(); i++)
|
||||
{
|
||||
Surface* surface = mesh->surfaces[i].get();
|
||||
|
||||
auto result = packer.insert(surface->texWidth + 2, surface->texHeight + 2);
|
||||
surface->atlasX = result.pos.x + 1;
|
||||
surface->atlasY = result.pos.y + 1;
|
||||
surface->atlasPageIndex = (int)result.pageIndex;
|
||||
}
|
||||
|
||||
for (size_t pageIndex = 0; pageIndex < packer.getNumPages(); pageIndex++)
|
||||
{
|
||||
atlasImages.push_back(CreateImage(atlasImageSize, atlasImageSize));
|
||||
}
|
||||
}
|
||||
|
||||
void GPURaytracer2::UploadUniforms()
|
||||
{
|
||||
Uniforms2 uniforms = {};
|
||||
uniforms.SunDir = mesh->map->GetSunDirection();
|
||||
uniforms.SunColor = mesh->map->GetSunColor();
|
||||
uniforms.SunIntensity = 1.0f;
|
||||
|
||||
mappedUniforms = (uint8_t*)uniformTransferBuffer->Map(0, uniformStructs * uniformStructStride);
|
||||
*reinterpret_cast<Uniforms2*>(mappedUniforms + uniformStructStride * uniformsIndex) = uniforms;
|
||||
uniformTransferBuffer->Unmap();
|
||||
|
||||
cmdbuffer->copyBuffer(uniformTransferBuffer.get(), uniformBuffer.get());
|
||||
PipelineBarrier()
|
||||
.AddBuffer(uniformBuffer.get(), VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT)
|
||||
.Execute(cmdbuffer.get(), VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
|
||||
}
|
||||
|
||||
void GPURaytracer2::ResolveAtlasImage(size_t i)
|
||||
{
|
||||
LightmapImage& img = atlasImages[i];
|
||||
|
||||
PipelineBarrier()
|
||||
.AddImage(img.raytrace.Image.get(), VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT)
|
||||
.Execute(cmdbuffer.get(), VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
|
||||
|
||||
RenderPassBegin()
|
||||
.RenderPass(resolve.renderPass.get())
|
||||
.RenderArea(0, 0, atlasImageSize, atlasImageSize)
|
||||
.Framebuffer(img.resolve.Framebuffer.get())
|
||||
.Execute(cmdbuffer.get());
|
||||
|
||||
VkDeviceSize offset = 0;
|
||||
cmdbuffer->bindVertexBuffers(0, 1, &sceneVertexBuffer->buffer, &offset);
|
||||
cmdbuffer->bindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, resolve.pipeline.get());
|
||||
|
||||
auto descriptorSet = resolve.descriptorPool->allocate(resolve.descriptorSetLayout.get());
|
||||
descriptorSet->SetDebugName("resolve.descriptorSet");
|
||||
WriteDescriptors()
|
||||
.AddCombinedImageSampler(descriptorSet.get(), 0, img.raytrace.View.get(), resolve.sampler.get(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
|
||||
.Execute(device.get());
|
||||
cmdbuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, resolve.pipelineLayout.get(), 0, descriptorSet.get());
|
||||
resolve.descriptorSets.push_back(std::move(descriptorSet));
|
||||
|
||||
VkViewport viewport = {};
|
||||
viewport.maxDepth = 1;
|
||||
viewport.width = (float)atlasImageSize;
|
||||
viewport.height = (float)atlasImageSize;
|
||||
cmdbuffer->setViewport(0, 1, &viewport);
|
||||
|
||||
PushConstants2 pc;
|
||||
pc.LightStart = 0;
|
||||
pc.LightEnd = 0;
|
||||
pc.SurfaceIndex = 0;
|
||||
pc.LightmapOrigin = vec3(0.0f);
|
||||
pc.LightmapStepX = vec3(0.0f);
|
||||
pc.LightmapStepY = vec3(0.0f);
|
||||
cmdbuffer->pushConstants(resolve.pipelineLayout.get(), VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(PushConstants2), &pc);
|
||||
|
||||
int firstVertex = sceneVertexPos;
|
||||
int vertexCount = 4;
|
||||
sceneVertexPos += vertexCount;
|
||||
SceneVertex* vertex = &sceneVertices[firstVertex];
|
||||
vertex[0].Position = vec2(0.0f, 0.0f);
|
||||
vertex[1].Position = vec2(1.0f, 0.0f);
|
||||
vertex[2].Position = vec2(1.0f, 1.0f);
|
||||
vertex[3].Position = vec2(0.0f, 1.0f);
|
||||
cmdbuffer->draw(vertexCount, 1, firstVertex, 0);
|
||||
|
||||
cmdbuffer->endRenderPass();
|
||||
|
||||
PipelineBarrier()
|
||||
.AddImage(img.resolve.Image.get(), VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT)
|
||||
.Execute(cmdbuffer.get(), VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
|
||||
|
||||
VkBufferImageCopy region = {};
|
||||
region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
region.imageSubresource.layerCount = 1;
|
||||
region.imageExtent.width = atlasImageSize;
|
||||
region.imageExtent.height = atlasImageSize;
|
||||
region.imageExtent.depth = 1;
|
||||
cmdbuffer->copyImageToBuffer(img.resolve.Image->image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, img.Transfer->buffer, 1, ®ion);
|
||||
}
|
||||
|
||||
void GPURaytracer2::DownloadAtlasImage(size_t pageIndex)
|
||||
{
|
||||
struct hvec4
|
||||
{
|
||||
unsigned short x, y, z, w;
|
||||
vec3 xyz() { return vec3(halfToFloat(x), halfToFloat(y), halfToFloat(z)); }
|
||||
};
|
||||
|
||||
hvec4* pixels = (hvec4*)atlasImages[pageIndex].Transfer->Map(0, atlasImageSize * atlasImageSize * sizeof(hvec4));
|
||||
|
||||
for (size_t i = 0; i < mesh->surfaces.size(); i++)
|
||||
{
|
||||
Surface* surface = mesh->surfaces[i].get();
|
||||
if (surface->atlasPageIndex != pageIndex)
|
||||
continue;
|
||||
|
||||
int atlasX = surface->atlasX;
|
||||
int atlasY = surface->atlasY;
|
||||
int sampleWidth = surface->texWidth;
|
||||
int sampleHeight = surface->texHeight;
|
||||
|
||||
for (int y = 0; y < sampleHeight; y++)
|
||||
{
|
||||
vec3* dest = &surface->texPixels[y * sampleWidth];
|
||||
hvec4* src = &pixels[atlasX + (atlasY + y) * atlasImageSize];
|
||||
for (int x = 0; x < sampleWidth; x++)
|
||||
{
|
||||
dest[x] = src[x].xyz();
|
||||
}
|
||||
}
|
||||
}
|
||||
atlasImages[pageIndex].Transfer->Unmap();
|
||||
}
|
||||
|
||||
vec2 GPURaytracer2::ToUV(const vec3& vert, const Surface* targetSurface)
|
||||
{
|
||||
vec3 localPos = vert - targetSurface->translateWorldToLocal;
|
||||
|
|
|
@ -97,6 +97,12 @@ private:
|
|||
void CreateSceneVertexBuffer();
|
||||
void CreateSceneLightBuffer();
|
||||
|
||||
void UploadUniforms();
|
||||
void CreateAtlasImages();
|
||||
void RenderAtlasImage(size_t pageIndex);
|
||||
void ResolveAtlasImage(size_t pageIndex);
|
||||
void DownloadAtlasImage(size_t pageIndex);
|
||||
|
||||
LightmapImage CreateImage(int width, int height);
|
||||
|
||||
void BeginCommands();
|
||||
|
@ -175,4 +181,7 @@ private:
|
|||
std::unique_ptr<VulkanFence> submitFence;
|
||||
std::unique_ptr<VulkanCommandPool> cmdpool;
|
||||
std::unique_ptr<VulkanCommandBuffer> cmdbuffer;
|
||||
|
||||
std::vector<LightmapImage> atlasImages;
|
||||
static const int atlasImageSize = 2048;
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue