diff --git a/include/Orange/Core/Result.h b/include/Orange/Core/Result.h index 9b06bf0..d04e55a 100644 --- a/include/Orange/Core/Result.h +++ b/include/Orange/Core/Result.h @@ -4,6 +4,7 @@ #include #include #include +#include namespace orange { @@ -101,6 +102,19 @@ namespace orange return Error(x.Code()); } + void Destroy() + { + if (m_created) + { + RefUnsafe().~T(); + m_created = false; + } + +#ifdef _DEBUG + std::memset(&m_data, 0, sizeof(T)); +#endif + } + protected: Result() = default; @@ -113,15 +127,6 @@ namespace orange return *this; } - void Destroy() - { - if (m_created) - { - RefUnsafe().~T(); - m_created = false; - } - } - Result& MakeError(ErrorCode code) { m_error = code; return *this; } Result& MakeSuccess() { m_error = SuccessCode; return *this; } diff --git a/include/Orange/Render/SmallPipeline.h b/include/Orange/Render/SmallPipeline.h new file mode 100644 index 0000000..b1d500e --- /dev/null +++ b/include/Orange/Render/SmallPipeline.h @@ -0,0 +1,154 @@ +#pragma once + +#include + +namespace orange +{ + struct MiniPipelineInfo + { + VkShaderModule vs; + VkShaderModule fs; + + VkPipelineLayout pipelineLayout; + + VkFormat colorFormat; + VkFormat depthFormat; + + bool enableDepthTest; + bool enableDepthWrites; + + Span vertexAttributes; + }; + + static VulkanResult CreateGraphicsPipeline(VkDevice device, const MiniPipelineInfo& info) + { + VkPipelineShaderStageCreateInfo stages[] = + { + { + .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, + .stage = VK_SHADER_STAGE_VERTEX_BIT, + .module = info.vs, + .pName = "main", + }, + { + .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, + .stage = VK_SHADER_STAGE_FRAGMENT_BIT, + .module = info.fs, + .pName = "main", + }, + }; + + Array dynamicStates = + { + VK_DYNAMIC_STATE_VIEWPORT, + VK_DYNAMIC_STATE_SCISSOR, + }; + + VkPipelineDynamicStateCreateInfo dynamicStateInfo = + { + .sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, + .dynamicStateCount = uint32_t(dynamicStates.size()), + .pDynamicStates = dynamicStates.data(), + }; + + VkVertexInputBindingDescription inputBindingDescription = + { + .binding = 0, + .stride = sizeof(StaticVertex), + .inputRate = VK_VERTEX_INPUT_RATE_VERTEX, + }; + + VkPipelineVertexInputStateCreateInfo vertexInputInfo = + { + .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, + .vertexBindingDescriptionCount = info.vertexAttributes.size ? 1u : 0u, + .pVertexBindingDescriptions = &inputBindingDescription, + .vertexAttributeDescriptionCount = uint32_t(info.vertexAttributes.size), + .pVertexAttributeDescriptions = info.vertexAttributes.data, + }; + + VkPipelineInputAssemblyStateCreateInfo inputAssemblyInfo = + { + .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, + .topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, + .primitiveRestartEnable = VK_FALSE, + }; + + VkPipelineViewportStateCreateInfo viewportStateInfo = + { + .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, + .viewportCount = 1, + .scissorCount = 1, + }; + + VkPipelineRasterizationStateCreateInfo rasterizationInfo = + { + .sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, + .cullMode = VK_CULL_MODE_BACK_BIT, + .frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE, + .lineWidth = 1.0f, + }; + + VkPipelineMultisampleStateCreateInfo multisampleInfo = + { + .sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, + .rasterizationSamples = VK_SAMPLE_COUNT_1_BIT, + }; + + VkPipelineDepthStencilStateCreateInfo depthStencilInfo = + { + .sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, + .depthTestEnable = info.enableDepthTest, + .depthWriteEnable = info.enableDepthWrites, + .depthCompareOp = VK_COMPARE_OP_LESS, + .minDepthBounds = 0.0f, + .maxDepthBounds = 1.0f, + }; + + VkPipelineColorBlendAttachmentState attachmentBlendState = + { + .colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | + VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT, + }; + + VkPipelineColorBlendStateCreateInfo colorBlendStateInfo = + { + .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, + .attachmentCount = 1, + .pAttachments = &attachmentBlendState, + }; + + VkPipelineRenderingCreateInfo renderingInfo = + { + .sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO, + .viewMask = 0u, + .colorAttachmentCount = 1u, + .pColorAttachmentFormats = &info.colorFormat, + .depthAttachmentFormat = info.depthFormat, + }; + + VkGraphicsPipelineCreateInfo pipelineInfo = + { + .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, + .pNext = &renderingInfo, + .stageCount = Size(stages), + .pStages = stages, + .pVertexInputState = &vertexInputInfo, + .pInputAssemblyState = &inputAssemblyInfo, + .pViewportState = &viewportStateInfo, + .pRasterizationState = &rasterizationInfo, + .pMultisampleState = &multisampleInfo, + .pDepthStencilState = &depthStencilInfo, + .pColorBlendState = &colorBlendStateInfo, + .pDynamicState = &dynamicStateInfo, + .layout = info.pipelineLayout, + }; + + VkPipeline pipeline = VK_NULL_HANDLE; + VkResult res = VK_SUCCESS; + if ((res = vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &pipeline)) != VK_SUCCESS) + return VulkanResult::Error(res); + + return VulkanResult::Success(pipeline); + } +} \ No newline at end of file diff --git a/include/Orange/Render/Swapchain.h b/include/Orange/Render/Swapchain.h index d8e3bd8..347d1be 100644 --- a/include/Orange/Render/Swapchain.h +++ b/include/Orange/Render/Swapchain.h @@ -16,7 +16,7 @@ namespace orange public: ~Swapchain(); - static Result Create(RenderContext& context, VkSurfaceKHR surface, bool hdr = false); + static Result Create(RenderContext& context, VkSurfaceKHR surface, bool hdr = false, bool srgbViews = false); VkImage Image() const { return m_images[m_currentImage]; } VkImageView ImageView() const { return m_imageViews[m_currentImage]; } diff --git a/src/Apps/Tools/ColorTester.cpp b/src/Apps/Tools/ColorTester.cpp new file mode 100644 index 0000000..8250299 --- /dev/null +++ b/src/Apps/Tools/ColorTester.cpp @@ -0,0 +1,473 @@ +#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 +#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("HDR Test"); + if (!r_renderContext) + return 1; + + auto r_surface = r_window->CreateSurface(r_renderContext->Instance()); + if (!r_surface) + return 1; + + const bool srgbViews = false; + bool swapchainWasHDR = true;//false; + auto r_swapchain = Swapchain::Create(*r_renderContext, *r_surface, swapchainWasHDR, srgbViews); + 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_ColorTester); + 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; + }; + + 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), + }); + + + uint32_t totalImageCount = 0; + struct ImageUpload + { + BufferSlice from; + VkImage to; + VkExtent3D extent; + }; + Vector imageUploads; + Vector imageIsHDR; + if (std::filesystem::exists("images")) + { + for (const auto &entry : std::filesystem::directory_iterator("images")) + { + std::cout << entry.path() << std::endl; + + bool imageHDR = true;//std::string(entry.path()).find(".pq.") != std::string::npos; + + auto r_pngData = fs::OpenFileIntoBuffer(entry.path().c_str()); + if (!r_pngData) + continue; + + spng_ctx *ctx = spng_ctx_new(0); + spng_set_png_buffer(ctx, r_pngData->data, r_pngData->size); + + struct spng_ihdr ihdr; + spng_get_ihdr(ctx, &ihdr); + + auto pngFmt = ihdr.bit_depth == 16 ? SPNG_FMT_RGBA16 : SPNG_FMT_RGBA8; + auto vkFormat = ihdr.bit_depth == 16 ? VK_FORMAT_R16G16B16A16_UNORM : VK_FORMAT_R8G8B8A8_UNORM; + + size_t pngOutSize = 0zu; + spng_decoded_image_size(ctx, pngFmt, &pngOutSize); + + std::cout << pngOutSize / 1024 / 1024 << "mb" << std::endl; + + auto pngLinearSlice = *pooler.AllocSlice(pngOutSize, 16); + spng_decode_image(ctx, pngLinearSlice.ptr, pngOutSize, pngFmt, 0); + spng_ctx_free(ctx); + + auto r_texture = r_renderContext->CreateImage(pooler, ihdr.width, ihdr.height, vkFormat, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT); + if (!r_texture) + return 1; + auto r_textureView = r_renderContext->CreateImageView(*r_texture, vkFormat, VK_IMAGE_ASPECT_COLOR_BIT); + if (!r_textureView) + return 1; + + VkDescriptorImageInfo descriptorImageInfo = + { + .imageView = *r_textureView, + .imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + }; + + VkWriteDescriptorSet writeImageDescriptorSet[] = + { + { + .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, + .dstSet = descriptorSet, + .dstBinding = 1, + .dstArrayElement = totalImageCount++, + .descriptorCount = 1, + .descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, + .pImageInfo = &descriptorImageInfo, + }, + }; + vkUpdateDescriptorSets(r_renderContext->Device(), Size(writeImageDescriptorSet), writeImageDescriptorSet, 0, nullptr); + + imageUploads.push_back(ImageUpload + { + .from = pngLinearSlice, + .to = *r_texture, + .extent = VkExtent3D{ ihdr.width, ihdr.height, 1u }, + }); + + imageIsHDR.push_back(imageHDR); + } + } + + 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); + + int32_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; + + if (handler.getFirst(Input::ButtonCodes::Key_Right)) + currentImageIdx++; + else if (handler.getFirst(Input::ButtonCodes::Key_Left)) + currentImageIdx--; + + currentImageIdx = currentImageIdx % totalImageCount; + + bool currentImageIsHDR = imageIsHDR[currentImageIdx]; + +#if 0 + if (swapchainWasHDR != currentImageIsHDR) + { + r_swapchain.Destroy(); + + r_swapchain = Swapchain::Create(*r_renderContext, *r_surface, currentImageIsHDR, srgbViews); + if (!r_swapchain) + return 1; + + swapchainWasHDR = currentImageIsHDR; + } +#endif + + VkCommandBuffer cmdBuf = r_swapchain->CommandBuffer(); + r_renderContext->BeginCommandBuffer(cmdBuf); + { + for (auto& upload : imageUploads) + { + VkImageMemoryBarrier transferBarrier = + { + .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, + .srcAccessMask = 0, + .dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, + .oldLayout = VK_IMAGE_LAYOUT_UNDEFINED, + .newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + .image = upload.to, + .subresourceRange = FirstColorMipSubresourceRange, + }; + vkCmdPipelineBarrier(cmdBuf, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, 1, &transferBarrier); + + VkBufferImageCopy region = + { + .bufferOffset = upload.from.offset, + .imageSubresource = + { + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .mipLevel = 0u, + .baseArrayLayer = 0u, + .layerCount = 1u, + }, + .imageExtent = upload.extent, + }; + vkCmdCopyBufferToImage(cmdBuf, upload.from.buffer, upload.to, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); + + VkImageMemoryBarrier optimalBarrier = + { + .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, + .srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, + .dstAccessMask = VK_ACCESS_MEMORY_READ_BIT, + .oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + .newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + .image = upload.to, + .subresourceRange = FirstColorMipSubresourceRange, + }; + vkCmdPipelineBarrier(cmdBuf, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, nullptr, 0, nullptr, 1, &optimalBarrier); + } + imageUploads.clear(); + + 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 = currentImageIdx, + .time = time, + }; + 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/HDRTest.cpp b/src/Apps/Tools/HDRTest.cpp index 81301b3..719e97e 100644 --- a/src/Apps/Tools/HDRTest.cpp +++ b/src/Apps/Tools/HDRTest.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -27,154 +28,6 @@ using namespace orange; -struct MiniPipelineInfo -{ - VkShaderModule vs; - VkShaderModule fs; - - VkPipelineLayout pipelineLayout; - - VkFormat colorFormat; - VkFormat depthFormat; - - bool enableDepthTest; - bool enableDepthWrites; - - Span vertexAttributes; -}; - -static VulkanResult CreateGraphicsPipeline(VkDevice device, const MiniPipelineInfo& info) -{ - VkPipelineShaderStageCreateInfo stages[] = - { - { - .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, - .stage = VK_SHADER_STAGE_VERTEX_BIT, - .module = info.vs, - .pName = "main", - }, - { - .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, - .stage = VK_SHADER_STAGE_FRAGMENT_BIT, - .module = info.fs, - .pName = "main", - }, - }; - - Array dynamicStates = - { - VK_DYNAMIC_STATE_VIEWPORT, - VK_DYNAMIC_STATE_SCISSOR, - }; - - VkPipelineDynamicStateCreateInfo dynamicStateInfo = - { - .sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, - .dynamicStateCount = uint32_t(dynamicStates.size()), - .pDynamicStates = dynamicStates.data(), - }; - - VkVertexInputBindingDescription inputBindingDescription = - { - .binding = 0, - .stride = sizeof(StaticVertex), - .inputRate = VK_VERTEX_INPUT_RATE_VERTEX, - }; - - VkPipelineVertexInputStateCreateInfo vertexInputInfo = - { - .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, - .vertexBindingDescriptionCount = info.vertexAttributes.size ? 1u : 0u, - .pVertexBindingDescriptions = &inputBindingDescription, - .vertexAttributeDescriptionCount = uint32_t(info.vertexAttributes.size), - .pVertexAttributeDescriptions = info.vertexAttributes.data, - }; - - VkPipelineInputAssemblyStateCreateInfo inputAssemblyInfo = - { - .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, - .topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, - .primitiveRestartEnable = VK_FALSE, - }; - - VkPipelineViewportStateCreateInfo viewportStateInfo = - { - .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, - .viewportCount = 1, - .scissorCount = 1, - }; - - VkPipelineRasterizationStateCreateInfo rasterizationInfo = - { - .sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, - .cullMode = VK_CULL_MODE_BACK_BIT, - .frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE, - .lineWidth = 1.0f, - }; - - VkPipelineMultisampleStateCreateInfo multisampleInfo = - { - .sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, - .rasterizationSamples = VK_SAMPLE_COUNT_1_BIT, - }; - - VkPipelineDepthStencilStateCreateInfo depthStencilInfo = - { - .sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, - .depthTestEnable = info.enableDepthTest, - .depthWriteEnable = info.enableDepthWrites, - .depthCompareOp = VK_COMPARE_OP_LESS, - .minDepthBounds = 0.0f, - .maxDepthBounds = 1.0f, - }; - - VkPipelineColorBlendAttachmentState attachmentBlendState = - { - .colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | - VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT, - }; - - VkPipelineColorBlendStateCreateInfo colorBlendStateInfo = - { - .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, - .attachmentCount = 1, - .pAttachments = &attachmentBlendState, - }; - - VkPipelineRenderingCreateInfo renderingInfo = - { - .sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO, - .viewMask = 0u, - .colorAttachmentCount = 1u, - .pColorAttachmentFormats = &info.colorFormat, - .depthAttachmentFormat = info.depthFormat, - }; - - VkGraphicsPipelineCreateInfo pipelineInfo = - { - .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, - .pNext = &renderingInfo, - .stageCount = Size(stages), - .pStages = stages, - .pVertexInputState = &vertexInputInfo, - .pInputAssemblyState = &inputAssemblyInfo, - .pViewportState = &viewportStateInfo, - .pRasterizationState = &rasterizationInfo, - .pMultisampleState = &multisampleInfo, - .pDepthStencilState = &depthStencilInfo, - .pColorBlendState = &colorBlendStateInfo, - .pDynamicState = &dynamicStateInfo, - .layout = info.pipelineLayout, - }; - - VkPipeline pipeline = VK_NULL_HANDLE; - VkResult res = VK_SUCCESS; - if ((res = vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &pipeline)) != VK_SUCCESS) - return VulkanResult::Error(res); - - return VulkanResult::Success(pipeline); -} - int main(int argc, char** argv) { (void)argc; (void)argv; diff --git a/src/Apps/Tools/meson.build b/src/Apps/Tools/meson.build index 40a9cad..f1fec69 100644 --- a/src/Apps/Tools/meson.build +++ b/src/Apps/Tools/meson.build @@ -12,3 +12,9 @@ executable('HDRTest', 'HDRTest.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_ColorTester.frag b/src/Orange/Render/Shaders/fs_ColorTester.frag new file mode 100644 index 0000000..a12f079 --- /dev/null +++ b/src/Orange/Render/Shaders/fs_ColorTester.frag @@ -0,0 +1,20 @@ +#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; +}; + +void main() +{ + out_color = texture(sampler2D(u_images[imageIndex], u_sampler), in_coords); +} \ No newline at end of file diff --git a/src/Orange/Render/Swapchain.cpp b/src/Orange/Render/Swapchain.cpp index b50e29f..bfb2a6d 100644 --- a/src/Orange/Render/Swapchain.cpp +++ b/src/Orange/Render/Swapchain.cpp @@ -31,6 +31,9 @@ namespace orange } else { + if (surfaceFormat.format == VK_FORMAT_A2B10G10R10_UNORM_PACK32 && surfaceFormat.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) + return Result::Success(surfaceFormat); + if (surfaceFormat.format == VK_FORMAT_B8G8R8A8_UNORM && surfaceFormat.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) return Result::Success(surfaceFormat); } @@ -78,7 +81,7 @@ namespace orange return imageCount; } - Result Swapchain::Create(RenderContext& context, VkSurfaceKHR surface, bool hdr) + Result Swapchain::Create(RenderContext& context, VkSurfaceKHR surface, bool hdr, bool srgbViews) { VkSurfaceCapabilitiesKHR capabilities; vkGetPhysicalDeviceSurfaceCapabilitiesKHR(context.PhysicalDevice(), surface, &capabilities); @@ -92,7 +95,7 @@ namespace orange VkFormat viewFormats[2] = { r_format->format, - FormatToSrgbFormat(r_format->format), + srgbViews ? FormatToSrgbFormat(r_format->format) : r_format->format, }; VkImageFormatListCreateInfo formatListInfo = @@ -138,7 +141,7 @@ namespace orange .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, .image = swapchainImages[i], .viewType = VK_IMAGE_VIEW_TYPE_2D, - .format = FormatToSrgbFormat(r_format->format), + .format = srgbViews ? FormatToSrgbFormat(r_format->format) : r_format->format, .subresourceRange = FirstColorMipSubresourceRange, }; @@ -191,8 +194,18 @@ namespace orange Swapchain::~Swapchain() { + vkQueueWaitIdle(m_ctx.Queue()); + for (const auto& imageView : m_imageViews) vkDestroyImageView(m_ctx.Device(), imageView, nullptr); + for (const auto& fence : m_inFlightFences) + vkDestroyFence(m_ctx.Device(), fence, nullptr); + for (const auto& semaphore : m_imageAvailableSemaphores) + vkDestroySemaphore(m_ctx.Device(), semaphore, nullptr); + for (const auto& semaphore : m_renderFinishedSemaphores) + vkDestroySemaphore(m_ctx.Device(), semaphore, nullptr); + for (const auto& cmdBuf : m_commandBuffers) + vkFreeCommandBuffers(m_ctx.Device(), m_ctx.CommandPool(), 1, &cmdBuf); vkDestroySwapchainKHR(m_ctx.Device(), m_swapchain, nullptr); } diff --git a/src/Orange/meson.build b/src/Orange/meson.build index 0d17a66..89853d2 100644 --- a/src/Orange/meson.build +++ b/src/Orange/meson.build @@ -1,6 +1,7 @@ orange_shaders = glsl_generator.process([ 'Render/Shaders/fs_DebugVertColor.frag', 'Render/Shaders/fs_Mesh.frag', + 'Render/Shaders/fs_ColorTester.frag', 'Render/Shaders/fs_Red.frag', 'Render/Shaders/fs_SkyGradient.frag', 'Render/Shaders/fs_HDRTest.frag',