diff --git a/examples/subpasses/subpasses.cpp b/examples/subpasses/subpasses.cpp index 8486c353..61209f37 100644 --- a/examples/subpasses/subpasses.cpp +++ b/examples/subpasses/subpasses.cpp @@ -21,8 +21,6 @@ #define ENABLE_VALIDATION false -#define NUM_LIGHTS 64 - class VulkanExample : public VulkanExampleBase { public: @@ -47,14 +45,12 @@ public: float radius; }; - struct { - Light lights[NUM_LIGHTS]; - } uboLights; + std::array lights; struct { vks::Buffer GBuffer; vks::Buffer lights; - } uniformBuffers; + } buffers; struct { VkPipeline offscreen; @@ -128,8 +124,8 @@ public: clearAttachment(&attachments.albedo); textures.glass.destroy(); - uniformBuffers.GBuffer.destroy(); - uniformBuffers.lights.destroy(); + buffers.GBuffer.destroy(); + buffers.lights.destroy(); } // Enable physical device features required for this example @@ -526,6 +522,7 @@ public: std::vector poolSizes = { vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 4), + vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1), vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 4), vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 4), }; @@ -556,7 +553,7 @@ public: VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSets.scene)); writeDescriptorSets = { // Binding 0: Vertex shader uniform buffer - vks::initializers::writeDescriptorSet(descriptorSets.scene, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffers.GBuffer.descriptor) + vks::initializers::writeDescriptorSet(descriptorSets.scene, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &buffers.GBuffer.descriptor) }; vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, NULL); } @@ -617,7 +614,7 @@ public: // Binding 2: Albedo input attachment vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, VK_SHADER_STAGE_FRAGMENT_BIT, 2), // Binding 3: Light positions - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT, 3), + vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT, 3), }; VkDescriptorSetLayoutCreateInfo descriptorLayout = @@ -648,7 +645,7 @@ public: // Binding 2: Albedo texture target vks::initializers::writeDescriptorSet(descriptorSets.composition, VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 2, &texDescriptorAlbedo), // Binding 4: Fragment shader lights - vks::initializers::writeDescriptorSet(descriptorSets.composition, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 3, &uniformBuffers.lights.descriptor), + vks::initializers::writeDescriptorSet(descriptorSets.composition, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 3, &buffers.lights.descriptor), }; vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, NULL); @@ -668,22 +665,6 @@ public: shaderStages[0] = loadShader(getShadersPath() + "subpasses/composition.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); shaderStages[1] = loadShader(getShadersPath() + "subpasses/composition.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - // Use specialization constants to pass number of lights to the shader - VkSpecializationMapEntry specializationEntry{}; - specializationEntry.constantID = 0; - specializationEntry.offset = 0; - specializationEntry.size = sizeof(uint32_t); - - uint32_t specializationData = NUM_LIGHTS; - - VkSpecializationInfo specializationInfo; - specializationInfo.mapEntryCount = 1; - specializationInfo.pMapEntries = &specializationEntry; - specializationInfo.dataSize = sizeof(specializationData); - specializationInfo.pData = &specializationData; - - shaderStages[1].pSpecializationInfo = &specializationInfo; - VkGraphicsPipelineCreateInfo pipelineCI = vks::initializers::pipelineCreateInfo(pipelineLayouts.composition, renderPass, 0); VkPipelineVertexInputStateCreateInfo emptyInputState{}; @@ -727,7 +708,7 @@ public: VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSets.transparent)); writeDescriptorSets = { - vks::initializers::writeDescriptorSet(descriptorSets.transparent, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffers.GBuffer.descriptor), + vks::initializers::writeDescriptorSet(descriptorSets.transparent, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &buffers.GBuffer.descriptor), vks::initializers::writeDescriptorSet(descriptorSets.transparent, VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1, &texDescriptorPosition), vks::initializers::writeDescriptorSet(descriptorSets.transparent, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2, &textures.glass.descriptor), }; @@ -755,13 +736,13 @@ public: // Prepare and initialize uniform buffer containing shader uniforms void prepareUniformBuffers() { - // Deferred vertex shader - vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &uniformBuffers.GBuffer, sizeof(uboGBuffer)); - VK_CHECK_RESULT(uniformBuffers.GBuffer.map()); + // Matrices + vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &buffers.GBuffer, sizeof(uboGBuffer)); + VK_CHECK_RESULT(buffers.GBuffer.map()); - // Deferred fragment shader - vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &uniformBuffers.lights, sizeof(uboLights)); - VK_CHECK_RESULT(uniformBuffers.lights.map()); + // Lights + vulkanDevice->createBuffer(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &buffers.lights, lights.size() * sizeof(Light)); + VK_CHECK_RESULT(buffers.lights.map()); // Update updateUniformBufferDeferredMatrices(); @@ -772,7 +753,7 @@ public: uboGBuffer.projection = camera.matrices.perspective; uboGBuffer.view = camera.matrices.view; uboGBuffer.model = glm::mat4(1.0f); - memcpy(uniformBuffers.GBuffer.mapped, &uboGBuffer, sizeof(uboGBuffer)); + memcpy(buffers.GBuffer.mapped, &uboGBuffer, sizeof(uboGBuffer)); } void initLights() @@ -786,18 +767,20 @@ public: glm::vec3(1.0f, 1.0f, 0.0f), }; - std::default_random_engine rndGen(benchmark.active ? 0 : (unsigned)time(nullptr)); + std::random_device rndDevice; + std::default_random_engine rndGen(benchmark.active ? 0 : rndDevice()); std::uniform_real_distribution rndDist(-1.0f, 1.0f); - std::uniform_int_distribution rndCol(0, static_cast(colors.size()-1)); + std::uniform_real_distribution rndCol(0.0f, 0.5f); - for (auto& light : uboLights.lights) + for (auto& light : lights) { light.position = glm::vec4(rndDist(rndGen) * 8.0f, 0.25f + std::abs(rndDist(rndGen)) * 4.0f, rndDist(rndGen) * 8.0f, 1.0f); - light.color = colors[rndCol(rndGen)]; + //light.color = colors[rndCol(rndGen)]; + light.color = glm::vec3(rndCol(rndGen), rndCol(rndGen), rndCol(rndGen)) * 2.0f; light.radius = 1.0f + std::abs(rndDist(rndGen)); } - memcpy(uniformBuffers.lights.mapped, &uboLights, sizeof(uboLights)); + memcpy(buffers.lights.mapped, lights.data(), lights.size() * sizeof(Light)); } void draw() diff --git a/shaders/glsl/subpasses/composition.frag b/shaders/glsl/subpasses/composition.frag index c060fe6f..0134c2a2 100644 --- a/shaders/glsl/subpasses/composition.frag +++ b/shaders/glsl/subpasses/composition.frag @@ -1,50 +1,47 @@ #version 450 -layout (input_attachment_index = 0, binding = 0) uniform subpassInput samplerposition; -layout (input_attachment_index = 1, binding = 1) uniform subpassInput samplerNormal; -layout (input_attachment_index = 2, binding = 2) uniform subpassInput samplerAlbedo; +layout (input_attachment_index = 0, binding = 0) uniform subpassInput inputPosition; +layout (input_attachment_index = 1, binding = 1) uniform subpassInput inputNormal; +layout (input_attachment_index = 2, binding = 2) uniform subpassInput inputAlbedo; layout (location = 0) in vec2 inUV; layout (location = 0) out vec4 outColor; -layout (constant_id = 0) const int NUM_LIGHTS = 64; - struct Light { vec4 position; vec3 color; float radius; }; -layout (binding = 3) uniform UBO +layout (std140, binding = 3) buffer LightsBuffer { - Light lights[NUM_LIGHTS]; -} ubo; - + Light lights[]; +}; void main() { // Read G-Buffer values from previous sub pass - vec3 fragPos = subpassLoad(samplerposition).rgb; - vec3 normal = subpassLoad(samplerNormal).rgb; - vec4 albedo = subpassLoad(samplerAlbedo); + vec3 fragPos = subpassLoad(inputPosition).rgb; + vec3 normal = subpassLoad(inputNormal).rgb; + vec4 albedo = subpassLoad(inputAlbedo); #define ambient 0.05 // Ambient part vec3 fragcolor = albedo.rgb * ambient; - for(int i = 0; i < NUM_LIGHTS; ++i) + for(int i = 0; i < lights.length(); ++i) { - vec3 L = ubo.lights[i].position.xyz - fragPos; + vec3 L = lights[i].position.xyz - fragPos; float dist = length(L); L = normalize(L); - float atten = ubo.lights[i].radius / (pow(dist, 3.0) + 1.0); + float atten = lights[i].radius / (pow(dist, 3.0) + 1.0); vec3 N = normalize(normal); float NdotL = max(0.0, dot(N, L)); - vec3 diff = ubo.lights[i].color * albedo.rgb * NdotL * atten; + vec3 diff = lights[i].color * albedo.rgb * NdotL * atten; fragcolor += diff; } diff --git a/shaders/glsl/subpasses/composition.frag.spv b/shaders/glsl/subpasses/composition.frag.spv index 8d620d0c..ceeb9732 100644 Binary files a/shaders/glsl/subpasses/composition.frag.spv and b/shaders/glsl/subpasses/composition.frag.spv differ diff --git a/shaders/hlsl/subpasses/composition.frag b/shaders/hlsl/subpasses/composition.frag index 29fd3113..6ded440b 100644 --- a/shaders/hlsl/subpasses/composition.frag +++ b/shaders/hlsl/subpasses/composition.frag @@ -1,11 +1,8 @@ // Copyright 2020 Google LLC -[[vk::input_attachment_index(0)]][[vk::binding(0)]] SubpassInput samplerposition; -[[vk::input_attachment_index(1)]][[vk::binding(1)]] SubpassInput samplerNormal; -[[vk::input_attachment_index(2)]][[vk::binding(2)]] SubpassInput samplerAlbedo; - -#define MAX_NUM_LIGHTS 64 -[[vk::constant_id(0)]] const int NUM_LIGHTS = 64; +[[vk::input_attachment_index(0)]][[vk::binding(0)]] SubpassInput inputPosition; +[[vk::input_attachment_index(1)]][[vk::binding(1)]] SubpassInput inputNormal; +[[vk::input_attachment_index(2)]][[vk::binding(2)]] SubpassInput inputAlbedo; struct Light { float4 position; @@ -13,56 +10,37 @@ struct Light { float radius; }; -struct UBO -{ - float4 viewPos; - Light lights[MAX_NUM_LIGHTS]; -}; - -cbuffer ubo : register(b3) { UBO ubo; } - +RWStructuredBuffer lights: register(u3); float4 main([[vk::location(0)]] float2 inUV : TEXCOORD) : SV_TARGET { // Read G-Buffer values from previous sub pass - float3 fragPos = samplerposition.SubpassLoad().rgb; - float3 normal = samplerNormal.SubpassLoad().rgb; - float4 albedo = samplerAlbedo.SubpassLoad(); + float3 fragPos = inputPosition.SubpassLoad().rgb; + float3 normal = inputNormal.SubpassLoad().rgb; + float4 albedo = inputAlbedo.SubpassLoad(); - #define ambient 0.15 + #define ambient 0.05 // Ambient part float3 fragcolor = albedo.rgb * ambient; - for(int i = 0; i < NUM_LIGHTS; ++i) + uint lightsLength; + uint lightsStride; + lights.GetDimensions(lightsLength, lightsStride); + + for(int i = 0; i < lightsLength; ++i) { - // Vector to light - float3 L = ubo.lights[i].position.xyz - fragPos; - // Distance from light to fragment position + float3 L = lights[i].position.xyz - fragPos; float dist = length(L); - // Viewer to fragment - float3 V = ubo.viewPos.xyz - fragPos; - V = normalize(V); - - // Light to fragment L = normalize(L); - // Attenuation - float atten = ubo.lights[i].radius / (pow(dist, 2.0) + 1.0); - - // Diffuse part + float atten = lights[i].radius / (pow(dist, 3.0) + 1.0); float3 N = normalize(normal); float NdotL = max(0.0, dot(N, L)); - float3 diff = ubo.lights[i].color * albedo.rgb * NdotL * atten; + float3 diff = lights[i].color * albedo.rgb * NdotL * atten; - // Specular part - // Specular map values are stored in alpha of albedo mrt - float3 R = reflect(-L, N); - float NdotR = max(0.0, dot(R, V)); - //float3 spec = ubo.lights[i].color * albedo.a * pow(NdotR, 32.0) * atten; - - fragcolor += diff;// + spec; + fragcolor += diff; } return float4(fragcolor, 1.0); diff --git a/shaders/hlsl/subpasses/composition.frag.spv b/shaders/hlsl/subpasses/composition.frag.spv index 380ebe6d..b0f438a9 100644 Binary files a/shaders/hlsl/subpasses/composition.frag.spv and b/shaders/hlsl/subpasses/composition.frag.spv differ