mirror of
https://github.com/ZDoom/ZDRay.git
synced 2025-02-03 13:11:04 +00:00
Trace sunlight on the GPU
This commit is contained in:
parent
b12f31f182
commit
ca5c48836f
5 changed files with 261 additions and 50 deletions
|
@ -6,13 +6,36 @@ static const char* glsl_closesthit = R"glsl(
|
||||||
struct hitPayload
|
struct hitPayload
|
||||||
{
|
{
|
||||||
float hitAttenuation;
|
float hitAttenuation;
|
||||||
|
bool isSkyRay;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SurfaceInfo
|
||||||
|
{
|
||||||
|
vec3 Normal;
|
||||||
|
float EmissiveDistance;
|
||||||
|
vec3 EmissiveColor;
|
||||||
|
float EmissiveIntensity;
|
||||||
|
float Sky;
|
||||||
|
float Padding0, Padding1, Padding2;
|
||||||
};
|
};
|
||||||
|
|
||||||
layout(location = 0) rayPayloadInEXT hitPayload payload;
|
layout(location = 0) rayPayloadInEXT hitPayload payload;
|
||||||
|
|
||||||
|
layout(set = 0, binding = 5) buffer SurfaceIndexBuffer { int surfaceIndices[]; };
|
||||||
|
layout(set = 0, binding = 6) buffer SurfaceBuffer { SurfaceInfo surfaces[]; };
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
payload.hitAttenuation = 0.0;
|
SurfaceInfo surface = surfaces[surfaceIndices[gl_PrimitiveID]];
|
||||||
|
|
||||||
|
if (!payload.isSkyRay)
|
||||||
|
{
|
||||||
|
payload.hitAttenuation = 0.0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
payload.hitAttenuation = surface.Sky;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
)glsl";
|
)glsl";
|
||||||
|
|
|
@ -6,13 +6,21 @@ static const char* glsl_miss = R"glsl(
|
||||||
struct hitPayload
|
struct hitPayload
|
||||||
{
|
{
|
||||||
float hitAttenuation;
|
float hitAttenuation;
|
||||||
|
bool isSkyRay;
|
||||||
};
|
};
|
||||||
|
|
||||||
layout(location = 0) rayPayloadInEXT hitPayload payload;
|
layout(location = 0) rayPayloadInEXT hitPayload payload;
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
payload.hitAttenuation = 1.0;
|
if (!payload.isSkyRay)
|
||||||
|
{
|
||||||
|
payload.hitAttenuation = 1.0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
payload.hitAttenuation = 0.0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
)glsl";
|
)glsl";
|
||||||
|
|
|
@ -6,6 +6,7 @@ static const char* glsl_raygen = R"glsl(
|
||||||
struct hitPayload
|
struct hitPayload
|
||||||
{
|
{
|
||||||
float hitAttenuation;
|
float hitAttenuation;
|
||||||
|
bool isSkyRay;
|
||||||
};
|
};
|
||||||
|
|
||||||
layout(location = 0) rayPayloadEXT hitPayload payload;
|
layout(location = 0) rayPayloadEXT hitPayload payload;
|
||||||
|
@ -60,47 +61,76 @@ void main()
|
||||||
emittance = imageLoad(outputs, texelPos);
|
emittance = imageLoad(outputs, texelPos);
|
||||||
|
|
||||||
const float minDistance = 0.01;
|
const float minDistance = 0.01;
|
||||||
float dist = distance(LightOrigin, origin);
|
const uint sample_count = 1024;
|
||||||
if (dist > minDistance && dist < LightRadius)
|
|
||||||
|
payload.isSkyRay = (PassType == 0.0);
|
||||||
|
if (!payload.isSkyRay)
|
||||||
{
|
{
|
||||||
vec3 dir = normalize(LightOrigin - origin);
|
float dist = distance(LightOrigin, origin);
|
||||||
|
if (dist > minDistance && dist < LightRadius)
|
||||||
float distAttenuation = max(1.0 - (dist / LightRadius), 0.0);
|
|
||||||
float angleAttenuation = max(dot(normal, dir), 0.0);
|
|
||||||
float spotAttenuation = 1.0;
|
|
||||||
if (LightOuterAngleCos > -1.0)
|
|
||||||
{
|
{
|
||||||
float cosDir = dot(dir, LightSpotDir);
|
vec3 dir = normalize(LightOrigin - origin);
|
||||||
spotAttenuation = smoothstep(LightOuterAngleCos, LightInnerAngleCos, cosDir);
|
|
||||||
spotAttenuation = max(spotAttenuation, 0.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
float attenuation = distAttenuation * angleAttenuation * spotAttenuation;
|
float distAttenuation = max(1.0 - (dist / LightRadius), 0.0);
|
||||||
if (attenuation > 0.0)
|
float angleAttenuation = max(dot(normal, dir), 0.0);
|
||||||
{
|
float spotAttenuation = 1.0;
|
||||||
const uint sample_count = 1024;
|
if (LightOuterAngleCos > -1.0)
|
||||||
float shadowAttenuation = 0.0;
|
|
||||||
vec3 e0 = cross(normal, abs(normal.x) < abs(normal.y) ? vec3(1.0, 0.0, 0.0) : vec3(0.0, 1.0, 0.0));
|
|
||||||
vec3 e1 = cross(normal, e0);
|
|
||||||
e0 = cross(normal, e1);
|
|
||||||
for (uint i = 0; i < sample_count; i++)
|
|
||||||
{
|
{
|
||||||
vec2 offset = (Hammersley(i, sample_count) - 0.5) * SampleDistance;
|
float cosDir = dot(dir, LightSpotDir);
|
||||||
vec3 origin2 = origin + offset.x * e0 + offset.y * e1;
|
spotAttenuation = smoothstep(LightOuterAngleCos, LightInnerAngleCos, cosDir);
|
||||||
|
spotAttenuation = max(spotAttenuation, 0.0);
|
||||||
float dist2 = distance(LightOrigin, origin2);
|
|
||||||
vec3 dir2 = normalize(LightOrigin - origin2);
|
|
||||||
|
|
||||||
traceRayEXT(acc, gl_RayFlagsOpaqueEXT, 0xff, 0, 0, 0, origin2, minDistance, dir2, dist2, 0);
|
|
||||||
shadowAttenuation += payload.hitAttenuation;
|
|
||||||
}
|
}
|
||||||
shadowAttenuation *= 1.0 / float(sample_count);
|
|
||||||
|
|
||||||
attenuation *= shadowAttenuation;
|
float attenuation = distAttenuation * angleAttenuation * spotAttenuation;
|
||||||
|
if (attenuation > 0.0)
|
||||||
|
{
|
||||||
|
float shadowAttenuation = 0.0;
|
||||||
|
vec3 e0 = cross(normal, abs(normal.x) < abs(normal.y) ? vec3(1.0, 0.0, 0.0) : vec3(0.0, 1.0, 0.0));
|
||||||
|
vec3 e1 = cross(normal, e0);
|
||||||
|
e0 = cross(normal, e1);
|
||||||
|
for (uint i = 0; i < sample_count; i++)
|
||||||
|
{
|
||||||
|
vec2 offset = (Hammersley(i, sample_count) - 0.5) * SampleDistance;
|
||||||
|
vec3 origin2 = origin + offset.x * e0 + offset.y * e1;
|
||||||
|
|
||||||
emittance.rgb += LightColor * (attenuation * LightIntensity);
|
float dist2 = distance(LightOrigin, origin2);
|
||||||
|
vec3 dir2 = normalize(LightOrigin - origin2);
|
||||||
|
|
||||||
|
traceRayEXT(acc, gl_RayFlagsOpaqueEXT, 0xff, 0, 0, 0, origin2, minDistance, dir2, dist2, 0);
|
||||||
|
shadowAttenuation += payload.hitAttenuation;
|
||||||
|
}
|
||||||
|
shadowAttenuation *= 1.0 / float(sample_count);
|
||||||
|
|
||||||
|
attenuation *= shadowAttenuation;
|
||||||
|
|
||||||
|
emittance.rgb += LightColor * (attenuation * LightIntensity);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
vec3 e0 = cross(normal, abs(normal.x) < abs(normal.y) ? vec3(1.0, 0.0, 0.0) : vec3(0.0, 1.0, 0.0));
|
||||||
|
vec3 e1 = cross(normal, e0);
|
||||||
|
e0 = cross(normal, e1);
|
||||||
|
|
||||||
|
origin += normal * 0.1;
|
||||||
|
|
||||||
|
float attenuation = 0.0;
|
||||||
|
for (uint i = 0; i < sample_count; i++)
|
||||||
|
{
|
||||||
|
vec2 offset = (Hammersley(i, sample_count) - 0.5) * SampleDistance;
|
||||||
|
vec3 origin2 = origin + offset.x * e0 + offset.y * e1;
|
||||||
|
|
||||||
|
float dist2 = 32768.0;
|
||||||
|
vec3 dir2 = LightSpotDir;
|
||||||
|
|
||||||
|
traceRayEXT(acc, gl_RayFlagsOpaqueEXT, 0xff, 0, 0, 0, origin2, minDistance, dir2, dist2, 0);
|
||||||
|
attenuation += payload.hitAttenuation;
|
||||||
|
}
|
||||||
|
attenuation *= 1.0 / float(sample_count);
|
||||||
|
|
||||||
|
emittance.rgb += LightColor * (attenuation * LightIntensity);
|
||||||
|
}
|
||||||
|
|
||||||
emittance.w += 1.0;
|
emittance.w += 1.0;
|
||||||
imageStore(outputs, texelPos, emittance);
|
imageStore(outputs, texelPos, emittance);
|
||||||
|
|
|
@ -191,7 +191,51 @@ void GPURaytracer::Raytrace(LevelMesh* level)
|
||||||
barrier2.addImage(outputImage.get(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, 0, VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT);
|
barrier2.addImage(outputImage.get(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, 0, VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT);
|
||||||
barrier2.execute(cmdbuffer.get(), VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR);
|
barrier2.execute(cmdbuffer.get(), VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR);
|
||||||
|
|
||||||
bool firstPass = true;
|
// Sunlight
|
||||||
|
{
|
||||||
|
Uniforms uniforms = {};
|
||||||
|
uniforms.LightOrigin = Vec3(0.0f, 0.0f, 0.0f);
|
||||||
|
uniforms.LightRadius = -1.0f;
|
||||||
|
uniforms.LightIntensity = 1.0f;
|
||||||
|
uniforms.LightInnerAngleCos = -1.0f;
|
||||||
|
uniforms.LightOuterAngleCos = -1.0f;
|
||||||
|
uniforms.LightSpotDir = mesh->map->GetSunDirection();
|
||||||
|
uniforms.LightColor = mesh->map->GetSunColor();
|
||||||
|
uniforms.PassType = 0.0f;
|
||||||
|
uniforms.SampleDistance = (float)mesh->samples;
|
||||||
|
|
||||||
|
auto data = uniformTransferBuffer->Map(0, sizeof(Uniforms));
|
||||||
|
memcpy(data, &uniforms, sizeof(Uniforms));
|
||||||
|
uniformTransferBuffer->Unmap();
|
||||||
|
|
||||||
|
cmdbuffer->copyBuffer(uniformTransferBuffer.get(), uniformBuffer.get());
|
||||||
|
|
||||||
|
PipelineBarrier barrier3;
|
||||||
|
barrier3.addBuffer(uniformBuffer.get(), VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT);
|
||||||
|
barrier3.execute(cmdbuffer.get(), VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR);
|
||||||
|
|
||||||
|
cmdbuffer->bindPipeline(VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipeline.get());
|
||||||
|
cmdbuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipelineLayout.get(), 0, descriptorSet.get());
|
||||||
|
cmdbuffer->traceRays(&rgenRegion, &missRegion, &hitRegion, &callRegion, rayTraceImageSize, rayTraceImageSize, 1);
|
||||||
|
|
||||||
|
cmdbuffer->end();
|
||||||
|
|
||||||
|
auto submitFence = std::make_unique<VulkanFence>(device.get());
|
||||||
|
|
||||||
|
QueueSubmit submit;
|
||||||
|
submit.addCommandBuffer(cmdbuffer.get());
|
||||||
|
submit.execute(device.get(), device->graphicsQueue, submitFence.get());
|
||||||
|
|
||||||
|
vkWaitForFences(device->device, 1, &submitFence->fence, VK_TRUE, std::numeric_limits<uint64_t>::max());
|
||||||
|
vkResetFences(device->device, 1, &submitFence->fence);
|
||||||
|
|
||||||
|
printf(".");
|
||||||
|
|
||||||
|
cmdbuffer.reset();
|
||||||
|
cmdbuffer = cmdpool->createBuffer();
|
||||||
|
cmdbuffer->begin();
|
||||||
|
}
|
||||||
|
|
||||||
for (ThingLight& light : mesh->map->ThingLights)
|
for (ThingLight& light : mesh->map->ThingLights)
|
||||||
{
|
{
|
||||||
Uniforms uniforms = {};
|
Uniforms uniforms = {};
|
||||||
|
@ -202,9 +246,8 @@ void GPURaytracer::Raytrace(LevelMesh* level)
|
||||||
uniforms.LightOuterAngleCos = light.outerAngleCos;
|
uniforms.LightOuterAngleCos = light.outerAngleCos;
|
||||||
uniforms.LightSpotDir = light.SpotDir();
|
uniforms.LightSpotDir = light.SpotDir();
|
||||||
uniforms.LightColor = light.rgb;
|
uniforms.LightColor = light.rgb;
|
||||||
uniforms.PassType = firstPass ? 0.0f : 1.0f;
|
uniforms.PassType = 1.0f;
|
||||||
uniforms.SampleDistance = (float)mesh->samples;
|
uniforms.SampleDistance = (float)mesh->samples;
|
||||||
firstPass = false;
|
|
||||||
|
|
||||||
auto data = uniformTransferBuffer->Map(0, sizeof(Uniforms));
|
auto data = uniformTransferBuffer->Map(0, sizeof(Uniforms));
|
||||||
memcpy(data, &uniforms, sizeof(Uniforms));
|
memcpy(data, &uniforms, sizeof(Uniforms));
|
||||||
|
@ -518,11 +561,64 @@ Vec3 GPURaytracer::GetSurfaceEmittance(Surface* surface, float distance)
|
||||||
|
|
||||||
void GPURaytracer::CreateVertexAndIndexBuffers()
|
void GPURaytracer::CreateVertexAndIndexBuffers()
|
||||||
{
|
{
|
||||||
|
std::vector<SurfaceInfo> surfaces;
|
||||||
|
surfaces.reserve(mesh->surfaces.size());
|
||||||
|
for (const auto& surface : mesh->surfaces)
|
||||||
|
{
|
||||||
|
SurfaceLightDef* def = nullptr;
|
||||||
|
if (surface->type >= ST_MIDDLESIDE && surface->type <= ST_LOWERSIDE)
|
||||||
|
{
|
||||||
|
int lightdefidx = mesh->map->Sides[surface->typeIndex].lightdef;
|
||||||
|
if (lightdefidx != -1)
|
||||||
|
{
|
||||||
|
def = &mesh->map->SurfaceLights[lightdefidx];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (surface->type == ST_FLOOR || surface->type == ST_CEILING)
|
||||||
|
{
|
||||||
|
MapSubsectorEx* sub = &mesh->map->GLSubsectors[surface->typeIndex];
|
||||||
|
IntSector* sector = mesh->map->GetSectorFromSubSector(sub);
|
||||||
|
|
||||||
|
if (sector && surface->numVerts > 0)
|
||||||
|
{
|
||||||
|
if (sector->floorlightdef != -1 && surface->type == ST_FLOOR)
|
||||||
|
{
|
||||||
|
def = &mesh->map->SurfaceLights[sector->floorlightdef];
|
||||||
|
}
|
||||||
|
else if (sector->ceilinglightdef != -1 && surface->type == ST_CEILING)
|
||||||
|
{
|
||||||
|
def = &mesh->map->SurfaceLights[sector->ceilinglightdef];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SurfaceInfo info;
|
||||||
|
info.Sky = surface->bSky ? 1.0f : 0.0f;
|
||||||
|
info.Normal = surface->plane.Normal();
|
||||||
|
if (def)
|
||||||
|
{
|
||||||
|
info.EmissiveDistance = def->distance;
|
||||||
|
info.EmissiveIntensity = def->intensity;
|
||||||
|
info.EmissiveColor = def->rgb;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
info.EmissiveDistance = 0.0f;
|
||||||
|
info.EmissiveIntensity = 0.0f;
|
||||||
|
info.EmissiveColor = Vec3(0.0f, 0.0f, 0.0f);
|
||||||
|
}
|
||||||
|
surfaces.push_back(info);
|
||||||
|
}
|
||||||
|
|
||||||
size_t vertexbuffersize = (size_t)mesh->MeshVertices.Size() * sizeof(Vec3);
|
size_t vertexbuffersize = (size_t)mesh->MeshVertices.Size() * sizeof(Vec3);
|
||||||
size_t indexbuffersize = (size_t)mesh->MeshElements.Size() * sizeof(uint32_t);
|
size_t indexbuffersize = (size_t)mesh->MeshElements.Size() * sizeof(uint32_t);
|
||||||
size_t transferbuffersize = vertexbuffersize + indexbuffersize;
|
size_t surfaceindexbuffersize = (size_t)mesh->MeshSurfaces.Size() * sizeof(uint32_t);
|
||||||
|
size_t surfacebuffersize = (size_t)surfaces.size() * sizeof(SurfaceInfo);
|
||||||
|
size_t transferbuffersize = vertexbuffersize + indexbuffersize + surfaceindexbuffersize + surfacebuffersize;
|
||||||
size_t vertexoffset = 0;
|
size_t vertexoffset = 0;
|
||||||
size_t indexoffset = vertexoffset + vertexbuffersize;
|
size_t indexoffset = vertexoffset + vertexbuffersize;
|
||||||
|
size_t surfaceindexoffset = indexoffset + indexbuffersize;
|
||||||
|
size_t surfaceoffset = surfaceindexoffset + surfaceindexbuffersize;
|
||||||
|
|
||||||
BufferBuilder vbuilder;
|
BufferBuilder vbuilder;
|
||||||
vbuilder.setUsage(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
|
vbuilder.setUsage(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
|
||||||
|
@ -536,6 +632,18 @@ void GPURaytracer::CreateVertexAndIndexBuffers()
|
||||||
indexBuffer = ibuilder.create(device.get());
|
indexBuffer = ibuilder.create(device.get());
|
||||||
indexBuffer->SetDebugName("indexBuffer");
|
indexBuffer->SetDebugName("indexBuffer");
|
||||||
|
|
||||||
|
BufferBuilder sibuilder;
|
||||||
|
sibuilder.setUsage(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
|
||||||
|
sibuilder.setSize(surfaceindexbuffersize);
|
||||||
|
surfaceIndexBuffer = sibuilder.create(device.get());
|
||||||
|
surfaceIndexBuffer->SetDebugName("surfaceIndexBuffer");
|
||||||
|
|
||||||
|
BufferBuilder sbuilder;
|
||||||
|
sbuilder.setUsage(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
|
||||||
|
sbuilder.setSize(surfacebuffersize);
|
||||||
|
surfaceBuffer = sbuilder.create(device.get());
|
||||||
|
surfaceBuffer->SetDebugName("surfaceBuffer");
|
||||||
|
|
||||||
BufferBuilder tbuilder;
|
BufferBuilder tbuilder;
|
||||||
tbuilder.setUsage(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY);
|
tbuilder.setUsage(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY);
|
||||||
tbuilder.setSize(transferbuffersize);
|
tbuilder.setSize(transferbuffersize);
|
||||||
|
@ -544,10 +652,14 @@ void GPURaytracer::CreateVertexAndIndexBuffers()
|
||||||
uint8_t* data = (uint8_t*)transferBuffer->Map(0, transferbuffersize);
|
uint8_t* data = (uint8_t*)transferBuffer->Map(0, transferbuffersize);
|
||||||
memcpy(data + vertexoffset, mesh->MeshVertices.Data(), vertexbuffersize);
|
memcpy(data + vertexoffset, mesh->MeshVertices.Data(), vertexbuffersize);
|
||||||
memcpy(data + indexoffset, mesh->MeshElements.Data(), indexbuffersize);
|
memcpy(data + indexoffset, mesh->MeshElements.Data(), indexbuffersize);
|
||||||
|
memcpy(data + surfaceindexoffset, mesh->MeshSurfaces.Data(), surfaceindexbuffersize);
|
||||||
|
memcpy(data + surfaceoffset, surfaces.data(), surfacebuffersize);
|
||||||
transferBuffer->Unmap();
|
transferBuffer->Unmap();
|
||||||
|
|
||||||
cmdbuffer->copyBuffer(transferBuffer.get(), vertexBuffer.get(), vertexoffset);
|
cmdbuffer->copyBuffer(transferBuffer.get(), vertexBuffer.get(), vertexoffset);
|
||||||
cmdbuffer->copyBuffer(transferBuffer.get(), indexBuffer.get(), indexoffset);
|
cmdbuffer->copyBuffer(transferBuffer.get(), indexBuffer.get(), indexoffset);
|
||||||
|
cmdbuffer->copyBuffer(transferBuffer.get(), surfaceIndexBuffer.get(), surfaceindexoffset);
|
||||||
|
cmdbuffer->copyBuffer(transferBuffer.get(), surfaceBuffer.get(), surfaceoffset);
|
||||||
|
|
||||||
VkMemoryBarrier barrier = { VK_STRUCTURE_TYPE_MEMORY_BARRIER };
|
VkMemoryBarrier barrier = { VK_STRUCTURE_TYPE_MEMORY_BARRIER };
|
||||||
barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||||
|
@ -725,20 +837,41 @@ void GPURaytracer::CreateTopLevelAccelerationStructure()
|
||||||
|
|
||||||
void GPURaytracer::CreateShaders()
|
void GPURaytracer::CreateShaders()
|
||||||
{
|
{
|
||||||
ShaderBuilder builder1;
|
try
|
||||||
builder1.setRayGenShader(glsl_raygen);
|
{
|
||||||
shaderRayGen = builder1.create(device.get());
|
ShaderBuilder builder;
|
||||||
shaderRayGen->SetDebugName("shaderRayGen");
|
builder.setRayGenShader(glsl_raygen);
|
||||||
|
shaderRayGen = builder.create(device.get());
|
||||||
|
shaderRayGen->SetDebugName("shaderRayGen");
|
||||||
|
}
|
||||||
|
catch (const std::exception& e)
|
||||||
|
{
|
||||||
|
throw std::runtime_error(std::string("Could not compile raygen shader: ") + e.what());
|
||||||
|
}
|
||||||
|
|
||||||
ShaderBuilder builder2;
|
try
|
||||||
builder2.setMissShader(glsl_miss);
|
{
|
||||||
shaderMiss = builder2.create(device.get());
|
ShaderBuilder builder;
|
||||||
shaderMiss->SetDebugName("shaderMiss");
|
builder.setMissShader(glsl_miss);
|
||||||
|
shaderMiss = builder.create(device.get());
|
||||||
|
shaderMiss->SetDebugName("shaderMiss");
|
||||||
|
}
|
||||||
|
catch (const std::exception& e)
|
||||||
|
{
|
||||||
|
throw std::runtime_error(std::string("Could not compile miss shader: ") + e.what());
|
||||||
|
}
|
||||||
|
|
||||||
ShaderBuilder builder;
|
try
|
||||||
builder.setClosestHitShader(glsl_closesthit);
|
{
|
||||||
shaderClosestHit = builder.create(device.get());
|
ShaderBuilder builder;
|
||||||
shaderClosestHit->SetDebugName("shaderClosestHit");
|
builder.setClosestHitShader(glsl_closesthit);
|
||||||
|
shaderClosestHit = builder.create(device.get());
|
||||||
|
shaderClosestHit->SetDebugName("shaderClosestHit");
|
||||||
|
}
|
||||||
|
catch (const std::exception& e)
|
||||||
|
{
|
||||||
|
throw std::runtime_error(std::string("Could not compile closest hit shader: ") + e.what());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GPURaytracer::CreatePipeline()
|
void GPURaytracer::CreatePipeline()
|
||||||
|
@ -749,6 +882,8 @@ void GPURaytracer::CreatePipeline()
|
||||||
setbuilder.addBinding(2, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, VK_SHADER_STAGE_RAYGEN_BIT_KHR);
|
setbuilder.addBinding(2, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, VK_SHADER_STAGE_RAYGEN_BIT_KHR);
|
||||||
setbuilder.addBinding(3, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, VK_SHADER_STAGE_RAYGEN_BIT_KHR);
|
setbuilder.addBinding(3, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, VK_SHADER_STAGE_RAYGEN_BIT_KHR);
|
||||||
setbuilder.addBinding(4, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_RAYGEN_BIT_KHR);
|
setbuilder.addBinding(4, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_RAYGEN_BIT_KHR);
|
||||||
|
setbuilder.addBinding(5, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR);
|
||||||
|
setbuilder.addBinding(6, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR);
|
||||||
descriptorSetLayout = setbuilder.create(device.get());
|
descriptorSetLayout = setbuilder.create(device.get());
|
||||||
descriptorSetLayout->SetDebugName("descriptorSetLayout");
|
descriptorSetLayout->SetDebugName("descriptorSetLayout");
|
||||||
|
|
||||||
|
@ -895,6 +1030,7 @@ void GPURaytracer::CreateDescriptorSet()
|
||||||
poolbuilder.addPoolSize(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 1);
|
poolbuilder.addPoolSize(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 1);
|
||||||
poolbuilder.addPoolSize(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 3);
|
poolbuilder.addPoolSize(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 3);
|
||||||
poolbuilder.addPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1);
|
poolbuilder.addPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1);
|
||||||
|
poolbuilder.addPoolSize(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 2);
|
||||||
poolbuilder.setMaxSets(1);
|
poolbuilder.setMaxSets(1);
|
||||||
descriptorPool = poolbuilder.create(device.get());
|
descriptorPool = poolbuilder.create(device.get());
|
||||||
descriptorPool->SetDebugName("descriptorPool");
|
descriptorPool->SetDebugName("descriptorPool");
|
||||||
|
@ -908,5 +1044,7 @@ void GPURaytracer::CreateDescriptorSet()
|
||||||
write.addStorageImage(descriptorSet.get(), 2, normalsImageView.get(), VK_IMAGE_LAYOUT_GENERAL);
|
write.addStorageImage(descriptorSet.get(), 2, normalsImageView.get(), VK_IMAGE_LAYOUT_GENERAL);
|
||||||
write.addStorageImage(descriptorSet.get(), 3, outputImageView.get(), VK_IMAGE_LAYOUT_GENERAL);
|
write.addStorageImage(descriptorSet.get(), 3, outputImageView.get(), VK_IMAGE_LAYOUT_GENERAL);
|
||||||
write.addBuffer(descriptorSet.get(), 4, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, uniformBuffer.get());
|
write.addBuffer(descriptorSet.get(), 4, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, uniformBuffer.get());
|
||||||
|
write.addBuffer(descriptorSet.get(), 5, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, surfaceIndexBuffer.get());
|
||||||
|
write.addBuffer(descriptorSet.get(), 6, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, surfaceBuffer.get());
|
||||||
write.updateSets(device.get());
|
write.updateSets(device.get());
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,16 @@ struct Uniforms
|
||||||
float Padding;
|
float Padding;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct SurfaceInfo
|
||||||
|
{
|
||||||
|
Vec3 Normal;
|
||||||
|
float EmissiveDistance;
|
||||||
|
Vec3 EmissiveColor;
|
||||||
|
float EmissiveIntensity;
|
||||||
|
float Sky;
|
||||||
|
float Padding0, Padding1, Padding2;
|
||||||
|
};
|
||||||
|
|
||||||
class GPURaytracer
|
class GPURaytracer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -56,6 +66,8 @@ private:
|
||||||
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> surfaceIndexBuffer;
|
||||||
|
std::unique_ptr<VulkanBuffer> surfaceBuffer;
|
||||||
|
|
||||||
std::unique_ptr<VulkanBuffer> blScratchBuffer;
|
std::unique_ptr<VulkanBuffer> blScratchBuffer;
|
||||||
std::unique_ptr<VulkanBuffer> blAccelStructBuffer;
|
std::unique_ptr<VulkanBuffer> blAccelStructBuffer;
|
||||||
|
|
Loading…
Reference in a new issue