From decbc12986d639b4d5488ae0179ab427094fbf57 Mon Sep 17 00:00:00 2001 From: Joshua Ashton Date: Sat, 13 Jan 2024 22:15:32 +0000 Subject: [PATCH] Add TDR Test --- src/Apps/Tools/TDRTest.cpp | 330 ++++++++++++++++++++++++++ src/Apps/Tools/meson.build | 5 + src/Orange/Render/Shaders/fs_TDR.frag | 44 ++++ src/Orange/meson.build | 1 + 4 files changed, 380 insertions(+) create mode 100644 src/Apps/Tools/TDRTest.cpp create mode 100644 src/Orange/Render/Shaders/fs_TDR.frag diff --git a/src/Apps/Tools/TDRTest.cpp b/src/Apps/Tools/TDRTest.cpp new file mode 100644 index 0000000..43078f3 --- /dev/null +++ b/src/Apps/Tools/TDRTest.cpp @@ -0,0 +1,330 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +using namespace orange; + +int main(int argc, char** argv) +{ + (void)argc; (void)argv; + + auto r_window = Window::Create(); + if (!r_window) + return 1; + + auto r_renderContext = RenderContext::Create("TDR Test"); + if (!r_renderContext) + return 1; + + auto r_surface = r_window->CreateSurface(r_renderContext->Instance()); + if (!r_surface) + return 1; + + auto r_swapchain = Swapchain::Create(*r_renderContext, *r_surface, false, true); + if (!r_swapchain) + return 1; + + auto r_buffer = r_renderContext->CreateBuffer(256 * 1024 * 1024); + if (!r_buffer) + return 1; + auto pooler = MemoryPool{ *r_buffer }; + + auto r_vsFullscreen = r_renderContext->CreateShader(vs_Fullscreen); + if (!r_vsFullscreen) return 1; + auto r_fsColorTester = r_renderContext->CreateShader(fs_TDR); + if (!r_fsColorTester) return 1; + + VkSamplerCreateInfo samplerInfo = + { + .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, + .magFilter = VK_FILTER_LINEAR, + .minFilter = VK_FILTER_LINEAR, + .mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR, + .addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, + .addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, + .addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, + .mipLodBias = 0.0f, + .anisotropyEnable = VK_TRUE, + .maxAnisotropy = 16.0f, + .minLod = -FLT_MAX, + .maxLod = FLT_MAX, + }; + VkSampler sampler = VK_NULL_HANDLE; + vkCreateSampler(r_renderContext->Device(), &samplerInfo, nullptr, &sampler); + + constexpr uint32_t MaxBindlessResources = 32768; + VkDescriptorPoolSize bindlessPoolSizes[] = + { + { VK_DESCRIPTOR_TYPE_SAMPLER, 1u}, + { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, MaxBindlessResources }, + }; + + VkDescriptorPoolCreateInfo poolInfo = + { + .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, + .flags = VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT, + .maxSets = 1u, + .poolSizeCount = uint32_t(Size(bindlessPoolSizes)), + .pPoolSizes = bindlessPoolSizes, + }; + + VkDescriptorPool descriptorPool = VK_NULL_HANDLE; + vkCreateDescriptorPool(r_renderContext->Device(), &poolInfo, nullptr, &descriptorPool); + + VkDescriptorSetLayoutBinding layoutBindings[] = + { + { + .binding = 0, + .descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER, + .descriptorCount = 1, + .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT, + .pImmutableSamplers = &sampler, + }, + { + .binding = 1, + .descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, + .descriptorCount = MaxBindlessResources, + .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT, + }, + }; + + constexpr VkDescriptorBindingFlags bindingFlags[] = + { + 0, + VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT_EXT | VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT_EXT | VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT, + }; + + Assert(Size(bindingFlags) == Size(layoutBindings)); + + VkDescriptorSetLayoutBindingFlagsCreateInfo layoutBindingFlagsInfo = + { + .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO_EXT, + .bindingCount = Size(bindingFlags), + .pBindingFlags = bindingFlags, + }; + + VkDescriptorSetLayoutCreateInfo layoutInfo = + { + .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, + .pNext = &layoutBindingFlagsInfo, + .flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT, + .bindingCount = Size(layoutBindings), + .pBindings = layoutBindings, + }; + + VkDescriptorSetLayout descriptorSetLayout = VK_NULL_HANDLE; + vkCreateDescriptorSetLayout(r_renderContext->Device(), &layoutInfo, nullptr, &descriptorSetLayout); + + VkDescriptorSetVariableDescriptorCountAllocateInfoEXT descriptorCountAllocInfo = + { + .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO_EXT, + .descriptorSetCount = 1, + .pDescriptorCounts = &MaxBindlessResources, + }; + + VkDescriptorSetAllocateInfo descriptorSetAllocInfo = + { + .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, + .pNext = &descriptorCountAllocInfo, + .descriptorPool = descriptorPool, + .descriptorSetCount = 1, + .pSetLayouts = &descriptorSetLayout, + }; + + VkDescriptorSet descriptorSet = VK_NULL_HANDLE; + vkAllocateDescriptorSets(r_renderContext->Device(), &descriptorSetAllocInfo, &descriptorSet); + + struct PushConstants + { + uint32_t frameIdx; + uint32_t imageIdx; + float time; + uint32_t loops; + }; + + VkPushConstantRange pushConstantRange = + { + .stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, + .offset = 0, + .size = sizeof(PushConstants), + }; + + VkPipelineLayoutCreateInfo pipelineLayoutInfo = + { + .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, + .setLayoutCount = 1, + .pSetLayouts = &descriptorSetLayout, + .pushConstantRangeCount = 1, + .pPushConstantRanges = &pushConstantRange, + }; + VkPipelineLayout pipelineLayout = VK_NULL_HANDLE; + vkCreatePipelineLayout(r_renderContext->Device(), &pipelineLayoutInfo, nullptr, &pipelineLayout); + + // + VkFormat depthFormat = *FindDepthFormat(r_renderContext->PhysicalDevice()); + auto pipeline = *CreateGraphicsPipeline(r_renderContext->Device(), MiniPipelineInfo + { + .vs = *r_vsFullscreen, + .fs = *r_fsColorTester, + .pipelineLayout = pipelineLayout, + .colorFormat = r_swapchain->Format(), + .depthFormat = depthFormat, + .enableDepthTest = false, + .enableDepthWrites = false, + .vertexAttributes = Span(nullptr), + }); + + struct FrameData + { + uint32_t testIdx; + }; + + auto frameDataSlice = *pooler.AllocSlice(MaxFramesInFlight * sizeof(FrameData), 16); + FrameData* frameData = reinterpret_cast(frameDataSlice.ptr); + + Input::InputHandler handler; + + r_window->EnableRelativeMouse(false); + + uint32_t currentImageIdx = 0; + auto t1 = Time::now(); + auto startTime = Time::now(); + uint32_t frameCounter = 0; + while (r_window->Update(handler)) + { + frameCounter++; + + const auto t2 = Time::now(); + auto delta = t2 - t1; + const float time = Seconds(startTime - t2).count(); + t1 = t2; + + VkCommandBuffer cmdBuf = r_swapchain->CommandBuffer(); + r_renderContext->BeginCommandBuffer(cmdBuf); + { + VkViewport viewport = + { + .x = 0.0f, + .y = 0.0f, + .width = float(r_swapchain->Extent().width), + .height = float(r_swapchain->Extent().height), + .minDepth = 0.0f, + .maxDepth = 1.0f, + }; + + VkRect2D scissor = + { + .offset = {0u, 0u}, + .extent = r_swapchain->Extent(), + }; + + vkCmdSetViewport(cmdBuf, 0, 1, &viewport); + vkCmdSetScissor(cmdBuf, 0, 1, &scissor); + + PushConstants pushConstants = + { + .frameIdx = frameCounter, + .imageIdx = 0u, + .time = time, + .loops = ~0u, + }; + vkCmdPushConstants(cmdBuf, pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(PushConstants), &pushConstants); + + vkCmdBindDescriptorSets(cmdBuf, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, nullptr); + + const VkImageMemoryBarrier undefinedToColorBarrier = + { + .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, + .dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + .oldLayout = VK_IMAGE_LAYOUT_UNDEFINED, + .newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + .image = r_swapchain->Image(), + .subresourceRange = FirstColorMipSubresourceRange, + }; + + vkCmdPipelineBarrier( + cmdBuf, + VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + 0, + 0, nullptr, + 0, nullptr, + 1, &undefinedToColorBarrier); + + const VkRenderingAttachmentInfoKHR colorAttachmentInfos[] = + { + { + .sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR, + .imageView = r_swapchain->ImageView(), + .imageLayout = VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL_KHR, + .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR, + .storeOp = VK_ATTACHMENT_STORE_OP_STORE, + .clearValue = { .color = { .float32 = { 1.0f, 1.0f, 1.0f, 1.0f } } }, + }, + }; + + const VkRenderingInfo renderInfo = + { + .sType = VK_STRUCTURE_TYPE_RENDERING_INFO, + .renderArea = { {}, r_swapchain->Extent() }, + .layerCount = 1, + .colorAttachmentCount = Size(colorAttachmentInfos), + .pColorAttachments = colorAttachmentInfos, + .pDepthAttachment = nullptr, + }; + vkCmdBeginRendering(cmdBuf, &renderInfo); + { + vkCmdBindPipeline(cmdBuf, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); + vkCmdDraw(cmdBuf, 3, 1, 0, 0); + } + vkCmdEndRendering(cmdBuf); + + const VkImageMemoryBarrier colorToPresentBarrier = + { + .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, + .srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + .oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + .newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, + .image = r_swapchain->Image(), + .subresourceRange = FirstColorMipSubresourceRange, + }; + + vkCmdPipelineBarrier( + cmdBuf, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, + 0, + 0, nullptr, + 0, nullptr, + 1, &colorToPresentBarrier); + } + r_renderContext->EndCommandBuffer(cmdBuf); + r_swapchain->Present(); + } + + return 0; +} diff --git a/src/Apps/Tools/meson.build b/src/Apps/Tools/meson.build index 13f9256..3cb2313 100644 --- a/src/Apps/Tools/meson.build +++ b/src/Apps/Tools/meson.build @@ -18,6 +18,11 @@ executable('HangTest', 'HangTest.cpp', orange_src, orange_shaders, xatlas_src, include_directories : [ orange_include, xatlas_include, joltphysics_include ] ) +executable('TDRTest', 'TDRTest.cpp', orange_src, orange_shaders, xatlas_src, + dependencies : [ sdl2_dep, vulkan_dep, spng_dep, miniz_dep ], + include_directories : [ orange_include, xatlas_include, joltphysics_include ] +) + executable('ColorTester', 'ColorTester.cpp', orange_src, orange_shaders, xatlas_src, dependencies : [ sdl2_dep, vulkan_dep, spng_dep, miniz_dep ], include_directories : [ orange_include, xatlas_include, joltphysics_include ] diff --git a/src/Orange/Render/Shaders/fs_TDR.frag b/src/Orange/Render/Shaders/fs_TDR.frag new file mode 100644 index 0000000..881b162 --- /dev/null +++ b/src/Orange/Render/Shaders/fs_TDR.frag @@ -0,0 +1,44 @@ +#version 450 +#extension GL_EXT_nonuniform_qualifier : require + +layout(location = 0) in vec2 in_coords; +layout(location = 0) out vec4 out_color; + +layout(set = 0, binding = 0) uniform sampler u_sampler; +layout(set = 0, binding = 1) uniform texture2D u_images[]; + +layout(push_constant) uniform p_constants_t +{ + uint frame; + uint imageIndex; + float time; + uint loop_iterations; +}; + +vec3 srgbToLinear(vec3 color) +{ + bvec3 isLo = lessThanEqual(color, vec3(0.04045f)); + + vec3 loPart = color / 12.92f; + vec3 hiPart = pow((color + 0.055f) / 1.055f, vec3(12.0f / 5.0f)); + return mix(hiPart, loPart, isLo); +} + +void main() +{ + out_color = vec4(0.0f); + for (uint i = 0; i < loop_iterations; i++) + { + for (uint j = 0; j < loop_iterations; j++) + { + for (uint w = 0; w < loop_iterations; w++) + { + const vec3 start = vec3(1.0f, 0.51f, 0.56f); + const vec3 end = vec3(0.48f, 0.76f, 0.84f); + vec2 coords = mix(start.xy, end.xy, vec2(float(j), float(i))) + in_coords; + out_color += texture(sampler2D(u_images[imageIndex], u_sampler), coords); + out_color.rgb = srgbToLinear(out_color.rgb); + } + } + } +} \ No newline at end of file diff --git a/src/Orange/meson.build b/src/Orange/meson.build index 89853d2..67b84a0 100644 --- a/src/Orange/meson.build +++ b/src/Orange/meson.build @@ -5,6 +5,7 @@ orange_shaders = glsl_generator.process([ 'Render/Shaders/fs_Red.frag', 'Render/Shaders/fs_SkyGradient.frag', 'Render/Shaders/fs_HDRTest.frag', + 'Render/Shaders/fs_TDR.frag', 'Render/Shaders/vs_Fullscreen.vert', 'Render/Shaders/vs_Mesh.vert', ])