From 9d0fd8ce5a6a34b6f509020527e06ac890d33909 Mon Sep 17 00:00:00 2001 From: Sascha Willems Date: Tue, 1 Sep 2020 21:51:06 +0200 Subject: [PATCH] Started work on variable rate shading sample --- .../glsl/variablerateshading/scene.frag | 43 +++ .../glsl/variablerateshading/scene.vert | 37 ++ examples/CMakeLists.txt | 1 + .../variablerateshading.cpp | 332 ++++++++++++++++++ .../variablerateshading/variablerateshading.h | 58 +++ 5 files changed, 471 insertions(+) create mode 100644 data/shaders/glsl/variablerateshading/scene.frag create mode 100644 data/shaders/glsl/variablerateshading/scene.vert create mode 100644 examples/variablerateshading/variablerateshading.cpp create mode 100644 examples/variablerateshading/variablerateshading.h diff --git a/data/shaders/glsl/variablerateshading/scene.frag b/data/shaders/glsl/variablerateshading/scene.frag new file mode 100644 index 00000000..4796f1ca --- /dev/null +++ b/data/shaders/glsl/variablerateshading/scene.frag @@ -0,0 +1,43 @@ +#version 450 + +#extension GL_NV_shading_rate_image : require + +layout (set = 1, binding = 0) uniform sampler2D samplerColorMap; +layout (set = 1, binding = 1) uniform sampler2D samplerNormalMap; + +layout (location = 0) in vec3 inNormal; +layout (location = 1) in vec3 inColor; +layout (location = 2) in vec2 inUV; +layout (location = 3) in vec3 inViewVec; +layout (location = 4) in vec3 inLightVec; +layout (location = 5) in vec4 inTangent; + +layout (location = 0) out vec4 outFragColor; + +layout (constant_id = 0) const bool ALPHA_MASK = false; +layout (constant_id = 1) const float ALPHA_MASK_CUTOFF = 0.0f; + +void main() +{ + vec4 color = texture(samplerColorMap, inUV) * vec4(inColor, 1.0); + + if (ALPHA_MASK) { + if (color.a < ALPHA_MASK_CUTOFF) { + discard; + } + } + + vec3 N = normalize(inNormal); + vec3 T = normalize(inTangent.xyz); + vec3 B = cross(inNormal, inTangent.xyz) * inTangent.w; + mat3 TBN = mat3(T, B, N); + N = TBN * normalize(texture(samplerNormalMap, inUV).xyz * 2.0 - vec3(1.0)); + + const float ambient = 0.1; + vec3 L = normalize(inLightVec); + vec3 V = normalize(inViewVec); + vec3 R = reflect(-L, N); + vec3 diffuse = max(dot(N, L), ambient).rrr; + float specular = pow(max(dot(R, V), 0.0), 32.0); + outFragColor = vec4(diffuse * color.rgb + specular, color.a); +} \ No newline at end of file diff --git a/data/shaders/glsl/variablerateshading/scene.vert b/data/shaders/glsl/variablerateshading/scene.vert new file mode 100644 index 00000000..7bfa122e --- /dev/null +++ b/data/shaders/glsl/variablerateshading/scene.vert @@ -0,0 +1,37 @@ +#version 450 + +layout (location = 0) in vec3 inPos; +layout (location = 1) in vec3 inNormal; +layout (location = 2) in vec2 inUV; +layout (location = 3) in vec3 inColor; +layout (location = 4) in vec4 inTangent; + +layout (set = 0, binding = 0) uniform UBOScene +{ + mat4 projection; + mat4 view; + mat4 model; + vec4 lightPos; + vec4 viewPos; +} uboScene; + +layout (location = 0) out vec3 outNormal; +layout (location = 1) out vec3 outColor; +layout (location = 2) out vec2 outUV; +layout (location = 3) out vec3 outViewVec; +layout (location = 4) out vec3 outLightVec; +layout (location = 5) out vec4 outTangent; + +void main() +{ + outNormal = inNormal; + outColor = inColor; + outUV = inUV; + outTangent = inTangent; + gl_Position = uboScene.projection * uboScene.view * uboScene.model * vec4(inPos.xyz, 1.0); + + outNormal = mat3(uboScene.model) * inNormal; + vec4 pos = uboScene.model * vec4(inPos, 1.0); + outLightVec = uboScene.lightPos.xyz - pos.xyz; + outViewVec = uboScene.viewPos.xyz - pos.xyz; +} \ No newline at end of file diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index f8311364..12c12e1b 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -122,6 +122,7 @@ set(EXAMPLES texturemipmapgen texturesparseresidency triangle + variablerateshading viewportarray vulkanscene ) diff --git a/examples/variablerateshading/variablerateshading.cpp b/examples/variablerateshading/variablerateshading.cpp new file mode 100644 index 00000000..f17ff520 --- /dev/null +++ b/examples/variablerateshading/variablerateshading.cpp @@ -0,0 +1,332 @@ +/* +* Vulkan Example - Variable rate shading +* +* Copyright (C) 2020 by Sascha Willems - www.saschawillems.de +* +* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) +*/ + +#include "variablerateshading.h" + +VulkanExample::VulkanExample() : VulkanExampleBase(ENABLE_VALIDATION) +{ + title = "Variable rate shading"; + apiVersion = VK_VERSION_1_1; + camera.type = Camera::CameraType::firstperson; + camera.setPosition(glm::vec3(0.0f, 1.0f, 0.0f)); + camera.setRotation(glm::vec3(0.0f, -90.0f, 0.0f)); + camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 256.0f); + settings.overlay = true; + enabledInstanceExtensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); + enabledDeviceExtensions.push_back(VK_NV_SHADING_RATE_IMAGE_EXTENSION_NAME); +} + +VulkanExample::~VulkanExample() +{ + vkDestroyPipelineLayout(device, pipelineLayout, nullptr); + shaderData.buffer.destroy(); +} + +void VulkanExample::getEnabledFeatures() +{ + enabledFeatures.samplerAnisotropy = deviceFeatures.samplerAnisotropy; + // POI + enabledPhysicalDeviceShadingRateImageFeaturesNV = {}; + enabledPhysicalDeviceShadingRateImageFeaturesNV.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADING_RATE_IMAGE_FEATURES_NV; + enabledPhysicalDeviceShadingRateImageFeaturesNV.shadingRateImage = VK_TRUE; + // @todo + deviceCreatepNextChain = &enabledPhysicalDeviceShadingRateImageFeaturesNV; +} + +void VulkanExample::buildCommandBuffers() +{ + VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); + + VkClearValue clearValues[2]; + clearValues[0].color = defaultClearColor; + clearValues[0].color = { { 0.25f, 0.25f, 0.25f, 1.0f } };; + clearValues[1].depthStencil = { 1.0f, 0 }; + + VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); + renderPassBeginInfo.renderPass = renderPass; + renderPassBeginInfo.renderArea.offset.x = 0; + renderPassBeginInfo.renderArea.offset.y = 0; + renderPassBeginInfo.renderArea.extent.width = width; + renderPassBeginInfo.renderArea.extent.height = height; + renderPassBeginInfo.clearValueCount = 2; + renderPassBeginInfo.pClearValues = clearValues; + + const VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f); + const VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0); + + for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) + { + renderPassBeginInfo.framebuffer = frameBuffers[i]; + VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); + vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); + vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); + vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); + vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); + vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, nullptr); + + // POI: todo + vkCmdBindShadingRateImageNV(drawCmdBuffers[i], shadingRateImage.view, VK_IMAGE_LAYOUT_SHADING_RATE_OPTIMAL_NV); + + scene.draw(drawCmdBuffers[i], vkglTF::RenderFlags::BindImages, pipelineLayout); + + drawUI(drawCmdBuffers[i]); + vkCmdEndRenderPass(drawCmdBuffers[i]); + VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); + } +} + +void VulkanExample::loadAssets() +{ + vkglTF::descriptorBindingFlags = vkglTF::DescriptorBindingFlags::ImageBaseColor | vkglTF::DescriptorBindingFlags::ImageNormalMap; + scene.loadFromFile(getAssetPath() + "models/sponza/sponza.gltf", vulkanDevice, queue, vkglTF::FileLoadingFlags::PreTransformVertices | vkglTF::FileLoadingFlags::FlipY); +} + +void VulkanExample::setupDescriptors() +{ + // Pool + const std::vector poolSizes = { + vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1), + }; + VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, 1); + VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); + + // Descriptor set layout + const std::vector setLayoutBindings = { + vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0), + }; + VkDescriptorSetLayoutCreateInfo descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); + VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayout)); + + // Pipeline layout + const std::vector setLayouts = { + descriptorSetLayout, + vkglTF::descriptorSetLayoutImage, + }; + VkPipelineLayoutCreateInfo pPipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(setLayouts.data(), 2); + VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pPipelineLayoutCreateInfo, nullptr, &pipelineLayout)); + + // Descriptor set + VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1); + VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet)); + std::vector writeDescriptorSets = { + vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &shaderData.buffer.descriptor), + }; + vkUpdateDescriptorSets(device, writeDescriptorSets.size(), writeDescriptorSets.data(), 0, NULL); +} + +// [POI] +void VulkanExample::prepareShadingRateImage() +{ + VkImageCreateInfo imageCI{}; + imageCI.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; + imageCI.imageType = VK_IMAGE_TYPE_2D; + imageCI.format = VK_FORMAT_R8_UINT; + imageCI.extent = { 512, 512, 1 }; + imageCI.mipLevels = 1; + imageCI.arrayLayers = 1; + imageCI.samples = VK_SAMPLE_COUNT_1_BIT; + imageCI.tiling = VK_IMAGE_TILING_OPTIMAL; + imageCI.usage = VK_IMAGE_USAGE_SHADING_RATE_IMAGE_BIT_NV | VK_IMAGE_USAGE_TRANSFER_DST_BIT; + VK_CHECK_RESULT(vkCreateImage(device, &imageCI, nullptr, &shadingRateImage.image)); + VkMemoryRequirements memReqs{}; + vkGetImageMemoryRequirements(device, shadingRateImage.image, &memReqs); + + VkMemoryAllocateInfo memAllloc{}; + memAllloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + memAllloc.allocationSize = memReqs.size; + memAllloc.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + VK_CHECK_RESULT(vkAllocateMemory(device, &memAllloc, nullptr, &shadingRateImage.memory)); + VK_CHECK_RESULT(vkBindImageMemory(device, shadingRateImage.image, shadingRateImage.memory, 0)); + + VkImageViewCreateInfo imageViewCI{}; + imageViewCI.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + imageViewCI.viewType = VK_IMAGE_VIEW_TYPE_2D; + imageViewCI.image = shadingRateImage.image; + imageViewCI.format = VK_FORMAT_R8_UINT; + imageViewCI.subresourceRange.baseMipLevel = 0; + imageViewCI.subresourceRange.levelCount = 1; + imageViewCI.subresourceRange.baseArrayLayer = 0; + imageViewCI.subresourceRange.layerCount = 1; + imageViewCI.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + VK_CHECK_RESULT(vkCreateImageView(device, &imageViewCI, nullptr, &shadingRateImage.view)); + + // Populate with shading rate pattern + const size_t bufferSize = 512 * 512 * sizeof(uint8_t); + uint8_t val = VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_PIXEL_NV; + uint8_t* shadingRatePatternData = new uint8_t[512 * 512]; + memset(shadingRatePatternData, val, bufferSize); + + VkBuffer stagingBuffer; + VkDeviceMemory stagingMemory; + + VkBufferCreateInfo bufferCreateInfo{}; + bufferCreateInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + bufferCreateInfo.size = bufferSize; + bufferCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; + bufferCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + VK_CHECK_RESULT(vkCreateBuffer(device, &bufferCreateInfo, nullptr, &stagingBuffer)); + VkMemoryAllocateInfo memAllocInfo{}; + memAllocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + memReqs = {}; + vkGetBufferMemoryRequirements(device, stagingBuffer, &memReqs); + memAllocInfo.allocationSize = memReqs.size; + memAllocInfo.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); + VK_CHECK_RESULT(vkAllocateMemory(device, &memAllocInfo, nullptr, &stagingMemory)); + VK_CHECK_RESULT(vkBindBufferMemory(device, stagingBuffer, stagingMemory, 0)); + + uint8_t* mapped; + VK_CHECK_RESULT(vkMapMemory(device, stagingMemory, 0, memReqs.size, 0, (void**)&mapped)); + memcpy(mapped, shadingRatePatternData, bufferSize); + vkUnmapMemory(device, stagingMemory); + + delete[] shadingRatePatternData; + + // Upload + VkCommandBuffer copyCmd = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); + VkImageSubresourceRange subresourceRange = {}; + subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + subresourceRange.levelCount = 1; + subresourceRange.layerCount = 1; + { + VkImageMemoryBarrier imageMemoryBarrier{}; + imageMemoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; + imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + imageMemoryBarrier.srcAccessMask = 0; + imageMemoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + imageMemoryBarrier.image = shadingRateImage.image; + imageMemoryBarrier.subresourceRange = subresourceRange; + vkCmdPipelineBarrier(copyCmd, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, 1, &imageMemoryBarrier); + } + VkBufferImageCopy bufferCopyRegion{}; + bufferCopyRegion.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + bufferCopyRegion.imageSubresource.layerCount = 1; + bufferCopyRegion.imageExtent.width = 512; + bufferCopyRegion.imageExtent.height = 512; + bufferCopyRegion.imageExtent.depth = 1; + vkCmdCopyBufferToImage(copyCmd, stagingBuffer, shadingRateImage.image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &bufferCopyRegion); + { + VkImageMemoryBarrier imageMemoryBarrier{}; + imageMemoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_SHADING_RATE_OPTIMAL_NV; + imageMemoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + imageMemoryBarrier.dstAccessMask = 0; + imageMemoryBarrier.image = shadingRateImage.image; + imageMemoryBarrier.subresourceRange = subresourceRange; + vkCmdPipelineBarrier(copyCmd, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, nullptr, 0, nullptr, 1, &imageMemoryBarrier); + } + vulkanDevice->flushCommandBuffer(copyCmd, queue, true); + + vkFreeMemory(device, stagingMemory, nullptr); + vkDestroyBuffer(device, stagingBuffer, nullptr); +} + +void VulkanExample::preparePipelines() +{ + VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCI = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); + VkPipelineRasterizationStateCreateInfo rasterizationStateCI = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_BACK_BIT, VK_FRONT_FACE_COUNTER_CLOCKWISE, 0); + VkPipelineColorBlendAttachmentState blendAttachmentStateCI = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); + VkPipelineColorBlendStateCreateInfo colorBlendStateCI = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentStateCI); + VkPipelineDepthStencilStateCreateInfo depthStencilStateCI = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE, VK_TRUE, VK_COMPARE_OP_LESS_OR_EQUAL); + VkPipelineViewportStateCreateInfo viewportStateCI = vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0); + VkPipelineMultisampleStateCreateInfo multisampleStateCI = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT, 0); + const std::vector dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; + VkPipelineDynamicStateCreateInfo dynamicStateCI = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables.data(), static_cast(dynamicStateEnables.size()), 0); + std::array shaderStages; + + // [POI] Per-Viewport shading rate palette entries + const std::vector shadingRatePaletteEntries = { + VK_SHADING_RATE_PALETTE_ENTRY_NO_INVOCATIONS_NV, + VK_SHADING_RATE_PALETTE_ENTRY_16_INVOCATIONS_PER_PIXEL_NV, + VK_SHADING_RATE_PALETTE_ENTRY_8_INVOCATIONS_PER_PIXEL_NV, + VK_SHADING_RATE_PALETTE_ENTRY_4_INVOCATIONS_PER_PIXEL_NV, + VK_SHADING_RATE_PALETTE_ENTRY_2_INVOCATIONS_PER_PIXEL_NV, + VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_PIXEL_NV, + VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_2X1_PIXELS_NV, + VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_1X2_PIXELS_NV, + VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_2X2_PIXELS_NV, + VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_4X2_PIXELS_NV, + VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_2X4_PIXELS_NV, + VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_4X4_PIXELS_NV, + }; + VkShadingRatePaletteNV shadingRatePalette{}; + shadingRatePalette.shadingRatePaletteEntryCount = static_cast(shadingRatePaletteEntries.size()); + shadingRatePalette.pShadingRatePaletteEntries = shadingRatePaletteEntries.data(); + VkPipelineViewportShadingRateImageStateCreateInfoNV pipelineViewportShadingRateImageStateCI{}; + pipelineViewportShadingRateImageStateCI.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_SHADING_RATE_IMAGE_STATE_CREATE_INFO_NV; + pipelineViewportShadingRateImageStateCI.shadingRateImageEnable = VK_TRUE; + pipelineViewportShadingRateImageStateCI.viewportCount = 1; + pipelineViewportShadingRateImageStateCI.pShadingRatePalettes = &shadingRatePalette; + viewportStateCI.pNext = &pipelineViewportShadingRateImageStateCI; + + VkGraphicsPipelineCreateInfo pipelineCI = vks::initializers::pipelineCreateInfo(pipelineLayout, renderPass, 0); + pipelineCI.pInputAssemblyState = &inputAssemblyStateCI; + pipelineCI.pRasterizationState = &rasterizationStateCI; + pipelineCI.pColorBlendState = &colorBlendStateCI; + pipelineCI.pMultisampleState = &multisampleStateCI; + pipelineCI.pViewportState = &viewportStateCI; + pipelineCI.pDepthStencilState = &depthStencilStateCI; + pipelineCI.pDynamicState = &dynamicStateCI; + pipelineCI.stageCount = static_cast(shaderStages.size()); + pipelineCI.pStages = shaderStages.data(); + pipelineCI.pVertexInputState = vkglTF::Vertex::getPipelineVertexInputState({ vkglTF::VertexComponent::Position, vkglTF::VertexComponent::Normal, vkglTF::VertexComponent::UV, vkglTF::VertexComponent::Color, vkglTF::VertexComponent::Tangent }); + + shaderStages[0] = loadShader(getShadersPath() + "variablerateshading/scene.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); + shaderStages[1] = loadShader(getShadersPath() + "variablerateshading/scene.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); + + VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipeline)); +} + +void VulkanExample::prepareUniformBuffers() +{ + VK_CHECK_RESULT(vulkanDevice->createBuffer( + VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, + &shaderData.buffer, + sizeof(shaderData.values))); + VK_CHECK_RESULT(shaderData.buffer.map()); + updateUniformBuffers(); +} + +void VulkanExample::updateUniformBuffers() +{ + shaderData.values.projection = camera.matrices.perspective; + shaderData.values.view = camera.matrices.view; + shaderData.values.viewPos = camera.viewPos; + memcpy(shaderData.buffer.mapped, &shaderData.values, sizeof(shaderData.values)); +} + +void VulkanExample::prepare() +{ + VulkanExampleBase::prepare(); + loadAssets(); + + vkCmdBindShadingRateImageNV = reinterpret_cast(vkGetDeviceProcAddr(device, "vkCmdBindShadingRateImageNV")); + + prepareShadingRateImage(); + prepareUniformBuffers(); + setupDescriptors(); + preparePipelines(); + buildCommandBuffers(); + prepared = true; +} + +void VulkanExample::render() +{ + renderFrame(); + if (camera.updated) { + updateUniformBuffers(); + } +} + +void VulkanExample::OnUpdateUIOverlay(vks::UIOverlay* overlay) +{ +} + +VULKAN_EXAMPLE_MAIN() \ No newline at end of file diff --git a/examples/variablerateshading/variablerateshading.h b/examples/variablerateshading/variablerateshading.h new file mode 100644 index 00000000..8d7aede2 --- /dev/null +++ b/examples/variablerateshading/variablerateshading.h @@ -0,0 +1,58 @@ +/* +* Vulkan Example - Variable rate shading +* +* Copyright (C) 2020 by Sascha Willems - www.saschawillems.de +* +* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) +*/ + +#include "vulkanexamplebase.h" +#include "VulkanglTFModel.h" + +#define ENABLE_VALIDATION false + +class VulkanExample : public VulkanExampleBase +{ +public: + vkglTF::Model scene; + + struct ShadingRateImage { + VkImage image; + VkDeviceMemory memory; + VkImageView view; + } shadingRateImage; + + struct ShaderData { + vks::Buffer buffer; + struct Values { + glm::mat4 projection; + glm::mat4 view; + glm::mat4 model = glm::mat4(1.0f); + glm::vec4 lightPos = glm::vec4(0.0f, -2.5f, 0.0f, 1.0f); + glm::vec4 viewPos; + } values; + } shaderData; + + VkPipeline pipeline; + VkPipelineLayout pipelineLayout; + VkDescriptorSet descriptorSet; + VkDescriptorSetLayout descriptorSetLayout; + + VkPhysicalDeviceShadingRateImageFeaturesNV enabledPhysicalDeviceShadingRateImageFeaturesNV; + PFN_vkCmdBindShadingRateImageNV vkCmdBindShadingRateImageNV; + + VulkanExample(); + ~VulkanExample(); + virtual void getEnabledFeatures(); + void buildCommandBuffers(); + void loadglTFFile(std::string filename); + void loadAssets(); + void prepareShadingRateImage(); + void setupDescriptors(); + void preparePipelines(); + void prepareUniformBuffers(); + void updateUniformBuffers(); + void prepare(); + virtual void render(); + virtual void OnUpdateUIOverlay(vks::UIOverlay* overlay); +}; \ No newline at end of file