@@ -142,6 +142,10 @@ static void cmdImageMemoryBarrier(vk::CommandBuffer cmdbuffer, vk::Image image,
142142static void cmdBeginRendering (vk::CommandBuffer cmdbuffer, uint32_t width, uint32_t height, const vk::RenderingAttachmentInfo& color, const vk::RenderingAttachmentInfo* depth = nullptr )
143143{
144144 cmdbuffer.beginRendering (vk::RenderingInfo{{}, vk::Rect2D{{0 , 0 }, {width, height}}, 1 , 0 , 1 , &color, depth});
145+ vk::Viewport viewport{0 .f , 0 .f , (float )width, (float )height, 0 .f , 1 .f };
146+ vk::Rect2D scissor{{0 , 0 }, {width, height}};
147+ cmdbuffer.setViewport (0 , 1 , &viewport);
148+ cmdbuffer.setScissor (0 , 1 , &scissor);
145149}
146150
147151static void cmdBeginRenderingLoad (vk::CommandBuffer cmdbuffer, vk::Image image, vk::ImageView view, uint32_t width, uint32_t height) // Render on top of the content of a color attachment written by a previous pass
@@ -713,12 +717,8 @@ void GPUDisplayBackendVulkan::clearTextureSampler()
713717
714718// ---------------------------- VULKAN SWAPCHAIN MANAGEMENT ----------------------------
715719
716- void GPUDisplayBackendVulkan::createSwapChain (bool forScreenshot, bool forMixing, vk::SwapchainKHR oldSwapChain)
720+ void GPUDisplayBackendVulkan::createSwapChain (vk::SwapchainKHR oldSwapChain)
717721{
718- mDownsampleFactor = getDownsampleFactor (forScreenshot);
719- mDownsampleFSAA = mDownsampleFactor != 1 ;
720- mSwapchainImageReadable = forScreenshot;
721-
722722 updateSwapChainDetails (mPhysicalDevice );
723723 mSurfaceFormat = chooseSwapSurfaceFormat (mSwapChainDetails .formats );
724724 mPresentMode = chooseSwapPresentMode (mSwapChainDetails .presentModes , mDisplay ->cfgR ().drawQualityVSync ? vk::PresentModeKHR::eMailbox : vk::PresentModeKHR::eImmediate);
@@ -731,8 +731,6 @@ void GPUDisplayBackendVulkan::createSwapChain(bool forScreenshot, bool forMixing
731731
732732 mScreenWidth = extent.width ;
733733 mScreenHeight = extent.height ;
734- mRenderWidth = mScreenWidth * mDownsampleFactor ;
735- mRenderHeight = mScreenHeight * mDownsampleFactor ;
736734
737735 vk::SwapchainCreateInfoKHR swapCreateInfo{};
738736 swapCreateInfo.surface = mSurface ;
@@ -741,7 +739,7 @@ void GPUDisplayBackendVulkan::createSwapChain(bool forScreenshot, bool forMixing
741739 swapCreateInfo.imageColorSpace = mSurfaceFormat .colorSpace ;
742740 swapCreateInfo.imageExtent = extent;
743741 swapCreateInfo.imageArrayLayers = 1 ;
744- swapCreateInfo.imageUsage = vk::ImageUsageFlagBits::eColorAttachment;
742+ swapCreateInfo.imageUsage = vk::ImageUsageFlagBits::eColorAttachment | vk::ImageUsageFlagBits::eTransferSrc | vk::ImageUsageFlagBits::eTransferDst; // Transfer for screenshots / FSAA downsampling, so that they need no swapchain recreation
745743 swapCreateInfo.imageSharingMode = vk::SharingMode::eExclusive;
746744 swapCreateInfo.queueFamilyIndexCount = 0 ; // Optional
747745 swapCreateInfo.pQueueFamilyIndices = nullptr ; // Optional
@@ -750,12 +748,6 @@ void GPUDisplayBackendVulkan::createSwapChain(bool forScreenshot, bool forMixing
750748 swapCreateInfo.presentMode = mPresentMode ;
751749 swapCreateInfo.clipped = true ;
752750 swapCreateInfo.oldSwapchain = oldSwapChain;
753- if (mSwapchainImageReadable ) {
754- swapCreateInfo.imageUsage |= vk::ImageUsageFlagBits::eTransferSrc;
755- }
756- if (mDownsampleFSAA ) {
757- swapCreateInfo.imageUsage |= vk::ImageUsageFlagBits::eTransferDst;
758- }
759751 mSwapChain = mDevice .createSwapchainKHR (swapCreateInfo, nullptr );
760752 if (oldSwapChain) {
761753 mDevice .destroySwapchainKHR (oldSwapChain, nullptr );
@@ -801,20 +793,26 @@ void GPUDisplayBackendVulkan::clearSwapChain(bool keepSwapChain)
801793
802794void GPUDisplayBackendVulkan::recreateRendering (bool forScreenshot, bool forMixing)
803795{
796+ needRecordCommandBuffers ();
797+ const bool needUpdateSwapChain = mMustUpdateSwapChain ;
798+ const bool needUpdateOffscreenBuffers = needUpdateSwapChain || mDownsampleFactor != getDownsampleFactor (forScreenshot) || mMSAASampleCount != getMSAASamplesFlag (std::min<uint32_t >(mMaxMSAAsupported , mDisplay ->cfgR ().drawQualityMSAA )) || mZActive != (mZSupported && mDisplay ->cfgL ().depthBuffer ) || mMixingSupported != forMixing;
799+ if (!needUpdateOffscreenBuffers) {
800+ return ;
801+ }
804802 mDevice .waitIdle ();
805- bool needUpdateSwapChain = mMustUpdateSwapChain || mDownsampleFactor != getDownsampleFactor (forScreenshot) || mSwapchainImageReadable != forScreenshot;
806- bool needUpdateOffscreenBuffers = needUpdateSwapChain || mMSAASampleCount != getMSAASamplesFlag (std::min<uint32_t >(mMaxMSAAsupported , mDisplay ->cfgR ().drawQualityMSAA )) || mZActive != (mZSupported && mDisplay ->cfgL ().depthBuffer ) || mMixingSupported != forMixing;
807- clearPipeline ();
808- if (needUpdateOffscreenBuffers) {
809- clearOffscreenBuffers ();
810- if (needUpdateSwapChain) {
811- clearSwapChain (true );
812- createSwapChain (forScreenshot, forMixing, mSwapChain );
813- }
814- createOffscreenBuffers (forScreenshot, forMixing);
803+ const vk::Format oldFormat = mSurfaceFormat .format ;
804+ const vk::SampleCountFlagBits oldMSAASampleCount = mMSAASampleCount ;
805+ const bool oldZActive = mZActive ;
806+ clearOffscreenBuffers ();
807+ if (needUpdateSwapChain) {
808+ clearSwapChain (true );
809+ createSwapChain (mSwapChain );
810+ }
811+ createOffscreenBuffers (forScreenshot, forMixing);
812+ if (mSurfaceFormat .format != oldFormat || mMSAASampleCount != oldMSAASampleCount || mZActive != oldZActive) { // Viewport / scissor are dynamic
813+ clearPipeline ();
814+ createPipeline ();
815815 }
816- createPipeline ();
817- needRecordCommandBuffers ();
818816 mUpdateUBOtextMatrix = mUpdateUBOmixMatrix = -1 ; // Screen / render size may have changed
819817}
820818
@@ -825,6 +823,10 @@ void GPUDisplayBackendVulkan::createOffscreenBuffers(bool forScreenshot, bool fo
825823 mMSAASampleCount = getMSAASamplesFlag (std::min<uint32_t >(mMaxMSAAsupported , mDisplay ->cfgR ().drawQualityMSAA ));
826824 mZActive = mZSupported && mDisplay ->cfgL ().depthBuffer ;
827825 mMixingSupported = forMixing;
826+ mDownsampleFactor = getDownsampleFactor (forScreenshot);
827+ mDownsampleFSAA = mDownsampleFactor != 1 ;
828+ mRenderWidth = mScreenWidth * mDownsampleFactor ;
829+ mRenderHeight = mScreenHeight * mDownsampleFactor ;
828830
829831 const uint32_t imageCountWithMixImages = mImageCount * (mMixingSupported ? 2 : 1 );
830832 mRenderTargetView .resize (imageCountWithMixImages);
@@ -929,23 +931,9 @@ void GPUDisplayBackendVulkan::createPipeline()
929931 // inputAssembly.topology // below
930932 inputAssembly.primitiveRestartEnable = false ;
931933
932- vk::Viewport viewport{};
933- viewport.x = 0 .0f ;
934- viewport.y = 0 .0f ;
935- // viewport.width // below
936- // viewport.height // below
937- viewport.minDepth = 0 .0f ;
938- viewport.maxDepth = 1 .0f ;
939-
940- vk::Rect2D scissor{};
941- scissor.offset = vk::Offset2D{0 , 0 };
942- // scissor.extent // below
943-
944- vk::PipelineViewportStateCreateInfo viewportState{};
934+ vk::PipelineViewportStateCreateInfo viewportState{}; // Viewport and scissor are dynamic
945935 viewportState.viewportCount = 1 ;
946- viewportState.pViewports = &viewport;
947936 viewportState.scissorCount = 1 ;
948- viewportState.pScissors = &scissor;
949937
950938 vk::PipelineRasterizationStateCreateInfo rasterizer{};
951939 rasterizer.depthClampEnable = false ;
@@ -995,9 +983,9 @@ void GPUDisplayBackendVulkan::createPipeline()
995983 depthStencil.depthBoundsTestEnable = false ;
996984 depthStencil.stencilTestEnable = false ;
997985
998- vk::DynamicState dynamicStates[] = {vk::DynamicState::eLineWidth};
986+ vk::DynamicState dynamicStates[] = {vk::DynamicState::eViewport, vk::DynamicState::eScissor, vk::DynamicState:: eLineWidth};
999987 vk::PipelineDynamicStateCreateInfo dynamicState{};
1000- dynamicState.dynamicStateCount = 1 ;
988+ // dynamicState.dynamicStateCount // below: viewport + scissor for text / texture, + line width for the main pipelines
1001989 dynamicState.pDynamicStates = dynamicStates;
1002990
1003991 vk::PushConstantRange pushConstantRanges[2 ] = {vk::PushConstantRange{}, vk::PushConstantRange{}};
@@ -1034,7 +1022,7 @@ void GPUDisplayBackendVulkan::createPipeline()
10341022 pipelineInfo.basePipelineHandle = VkPipeline (VK_NULL_HANDLE ); // Optional
10351023 pipelineInfo.basePipelineIndex = -1 ; // Optional
10361024
1037- mPipelines .resize (mMixingSupported ? 5 : 4 );
1025+ mPipelines .resize (5 );
10381026 static constexpr vk::PrimitiveTopology types[3 ] = {vk::PrimitiveTopology::ePointList, vk::PrimitiveTopology::eLineList, vk::PrimitiveTopology::eLineStrip};
10391027 for (uint32_t i = 0 ; i < mPipelines .size (); i++) {
10401028 if (i == 4 ) { // Texture rendering
@@ -1043,26 +1031,24 @@ void GPUDisplayBackendVulkan::createPipeline()
10431031 inputAssembly.topology = vk::PrimitiveTopology::eTriangleList;
10441032 vertShaderStageInfo.module = mShaders [" vertexTexture" ];
10451033 fragShaderStageInfo.module = mShaders [" fragmentTexture" ];
1034+ dynamicState.dynamicStateCount = 2 ;
10461035 pipelineInfo.layout = mPipelineLayoutTexture ;
10471036 renderingInfo.depthAttachmentFormat = vk::Format::eUndefined;
10481037 pipelineInfo.pDepthStencilState = nullptr ;
10491038 colorBlendAttachment.blendEnable = true ;
10501039 multisampling.rasterizationSamples = vk::SampleCountFlagBits::e1 ;
1051- viewport.width = scissor.extent .width = mRenderWidth ;
1052- viewport.height = scissor.extent .height = mRenderHeight ;
10531040 } else if (i == 3 ) { // Text rendering
10541041 bindingDescription.stride = 4 * sizeof (float );
10551042 attributeDescriptions.format = vk::Format::eR32G32B32A32Sfloat;
10561043 inputAssembly.topology = vk::PrimitiveTopology::eTriangleList;
10571044 vertShaderStageInfo.module = mShaders [" vertexTexture" ];
10581045 fragShaderStageInfo.module = mShaders [" fragmentText" ];
1046+ dynamicState.dynamicStateCount = 2 ;
10591047 pipelineInfo.layout = mPipelineLayoutTexture ;
10601048 renderingInfo.depthAttachmentFormat = vk::Format::eUndefined;
10611049 pipelineInfo.pDepthStencilState = nullptr ;
10621050 colorBlendAttachment.blendEnable = true ;
10631051 multisampling.rasterizationSamples = vk::SampleCountFlagBits::e1 ;
1064- viewport.width = scissor.extent .width = mScreenWidth ;
1065- viewport.height = scissor.extent .height = mScreenHeight ;
10661052 } else { // Point / line / line-strip rendering
10671053 bindingDescription.stride = 3 * sizeof (float );
10681054 attributeDescriptions.format = vk::Format::eR32G32B32Sfloat;
@@ -1072,10 +1058,9 @@ void GPUDisplayBackendVulkan::createPipeline()
10721058 pipelineInfo.layout = mPipelineLayout ;
10731059 renderingInfo.depthAttachmentFormat = mZActive ? vk::Format::eD32Sfloat : vk::Format::eUndefined;
10741060 pipelineInfo.pDepthStencilState = mZActive ? &depthStencil : nullptr ;
1061+ dynamicState.dynamicStateCount = 3 ;
10751062 colorBlendAttachment.blendEnable = true ;
10761063 multisampling.rasterizationSamples = mMSAASampleCount ;
1077- viewport.width = scissor.extent .width = mRenderWidth ;
1078- viewport.height = scissor.extent .height = mRenderHeight ;
10791064 }
10801065
10811066 CHKERR (mDevice .createGraphicsPipelines (VkPipelineCache (VK_NULL_HANDLE ), 1 , &pipelineInfo, nullptr , &mPipelines [i])); // TODO: multiple at once + cache?
@@ -1389,7 +1374,7 @@ void GPUDisplayBackendVulkan::prepareDraw(const hmm_mat4& proj, const hmm_mat4&
13891374 };
13901375
13911376 vk::Result retVal = vk::Result::eSuccess;
1392- bool mustUpdateSwapChain = mMustUpdateSwapChain || mDisplay ->updateRenderPipeline () || (requestScreenshot && ! mSwapchainImageReadable ) || ( toMixBuffer && !mMixingSupported ) || mDownsampleFactor != getDownsampleFactor (requestScreenshot);
1377+ bool mustUpdateSwapChain = mMustUpdateSwapChain || mDisplay ->updateRenderPipeline () || (toMixBuffer && !mMixingSupported ) || mDownsampleFactor != getDownsampleFactor (requestScreenshot);
13931378 if (!mustUpdateSwapChain) {
13941379 retVal = getImage ();
13951380 if (retVal == vk::Result::eErrorOutOfDateKHR) {
0 commit comments