diff options
| author | 2024-01-22 12:40:50 -0500 | |
|---|---|---|
| committer | 2024-02-09 09:20:53 -0500 | |
| commit | 962c82540c304f909957776908aabcd261f2a7ba (patch) | |
| tree | 707ab34565e8309b5ede21acebf36975da7718e7 /src/video_core/renderer_vulkan | |
| parent | nvservices: unmap only on last container free (diff) | |
| download | yuzu-962c82540c304f909957776908aabcd261f2a7ba.tar.gz yuzu-962c82540c304f909957776908aabcd261f2a7ba.tar.xz yuzu-962c82540c304f909957776908aabcd261f2a7ba.zip | |
nvnflinger/gpu: implement blending
Diffstat (limited to 'src/video_core/renderer_vulkan')
6 files changed, 102 insertions, 41 deletions
diff --git a/src/video_core/renderer_vulkan/present/util.cpp b/src/video_core/renderer_vulkan/present/util.cpp index 6ee16595d..7f27c7c1b 100644 --- a/src/video_core/renderer_vulkan/present/util.cpp +++ b/src/video_core/renderer_vulkan/present/util.cpp | |||
| @@ -362,10 +362,10 @@ vk::PipelineLayout CreateWrappedPipelineLayout(const Device& device, | |||
| 362 | }); | 362 | }); |
| 363 | } | 363 | } |
| 364 | 364 | ||
| 365 | vk::Pipeline CreateWrappedPipeline(const Device& device, vk::RenderPass& renderpass, | 365 | static vk::Pipeline CreateWrappedPipelineImpl( |
| 366 | vk::PipelineLayout& layout, | 366 | const Device& device, vk::RenderPass& renderpass, vk::PipelineLayout& layout, |
| 367 | std::tuple<vk::ShaderModule&, vk::ShaderModule&> shaders, | 367 | std::tuple<vk::ShaderModule&, vk::ShaderModule&> shaders, |
| 368 | bool enable_blending) { | 368 | VkPipelineColorBlendAttachmentState blending) { |
| 369 | const std::array<VkPipelineShaderStageCreateInfo, 2> shader_stages{{ | 369 | const std::array<VkPipelineShaderStageCreateInfo, 2> shader_stages{{ |
| 370 | { | 370 | { |
| 371 | .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, | 371 | .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, |
| @@ -443,30 +443,6 @@ vk::Pipeline CreateWrappedPipeline(const Device& device, vk::RenderPass& renderp | |||
| 443 | .alphaToOneEnable = VK_FALSE, | 443 | .alphaToOneEnable = VK_FALSE, |
| 444 | }; | 444 | }; |
| 445 | 445 | ||
| 446 | constexpr VkPipelineColorBlendAttachmentState color_blend_attachment_disabled{ | ||
| 447 | .blendEnable = VK_FALSE, | ||
| 448 | .srcColorBlendFactor = VK_BLEND_FACTOR_ZERO, | ||
| 449 | .dstColorBlendFactor = VK_BLEND_FACTOR_ZERO, | ||
| 450 | .colorBlendOp = VK_BLEND_OP_ADD, | ||
| 451 | .srcAlphaBlendFactor = VK_BLEND_FACTOR_ZERO, | ||
| 452 | .dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO, | ||
| 453 | .alphaBlendOp = VK_BLEND_OP_ADD, | ||
| 454 | .colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | | ||
| 455 | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT, | ||
| 456 | }; | ||
| 457 | |||
| 458 | constexpr VkPipelineColorBlendAttachmentState color_blend_attachment_enabled{ | ||
| 459 | .blendEnable = VK_TRUE, | ||
| 460 | .srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA, | ||
| 461 | .dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, | ||
| 462 | .colorBlendOp = VK_BLEND_OP_ADD, | ||
| 463 | .srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE, | ||
| 464 | .dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO, | ||
| 465 | .alphaBlendOp = VK_BLEND_OP_ADD, | ||
| 466 | .colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | | ||
| 467 | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT, | ||
| 468 | }; | ||
| 469 | |||
| 470 | const VkPipelineColorBlendStateCreateInfo color_blend_ci{ | 446 | const VkPipelineColorBlendStateCreateInfo color_blend_ci{ |
| 471 | .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, | 447 | .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, |
| 472 | .pNext = nullptr, | 448 | .pNext = nullptr, |
| @@ -474,8 +450,7 @@ vk::Pipeline CreateWrappedPipeline(const Device& device, vk::RenderPass& renderp | |||
| 474 | .logicOpEnable = VK_FALSE, | 450 | .logicOpEnable = VK_FALSE, |
| 475 | .logicOp = VK_LOGIC_OP_COPY, | 451 | .logicOp = VK_LOGIC_OP_COPY, |
| 476 | .attachmentCount = 1, | 452 | .attachmentCount = 1, |
| 477 | .pAttachments = | 453 | .pAttachments = &blending, |
| 478 | enable_blending ? &color_blend_attachment_enabled : &color_blend_attachment_disabled, | ||
| 479 | .blendConstants = {0.0f, 0.0f, 0.0f, 0.0f}, | 454 | .blendConstants = {0.0f, 0.0f, 0.0f, 0.0f}, |
| 480 | }; | 455 | }; |
| 481 | 456 | ||
| @@ -515,6 +490,63 @@ vk::Pipeline CreateWrappedPipeline(const Device& device, vk::RenderPass& renderp | |||
| 515 | }); | 490 | }); |
| 516 | } | 491 | } |
| 517 | 492 | ||
| 493 | vk::Pipeline CreateWrappedPipeline(const Device& device, vk::RenderPass& renderpass, | ||
| 494 | vk::PipelineLayout& layout, | ||
| 495 | std::tuple<vk::ShaderModule&, vk::ShaderModule&> shaders) { | ||
| 496 | constexpr VkPipelineColorBlendAttachmentState color_blend_attachment_disabled{ | ||
| 497 | .blendEnable = VK_FALSE, | ||
| 498 | .srcColorBlendFactor = VK_BLEND_FACTOR_ZERO, | ||
| 499 | .dstColorBlendFactor = VK_BLEND_FACTOR_ZERO, | ||
| 500 | .colorBlendOp = VK_BLEND_OP_ADD, | ||
| 501 | .srcAlphaBlendFactor = VK_BLEND_FACTOR_ZERO, | ||
| 502 | .dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO, | ||
| 503 | .alphaBlendOp = VK_BLEND_OP_ADD, | ||
| 504 | .colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | | ||
| 505 | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT, | ||
| 506 | }; | ||
| 507 | |||
| 508 | return CreateWrappedPipelineImpl(device, renderpass, layout, shaders, | ||
| 509 | color_blend_attachment_disabled); | ||
| 510 | } | ||
| 511 | |||
| 512 | vk::Pipeline CreateWrappedPremultipliedBlendingPipeline( | ||
| 513 | const Device& device, vk::RenderPass& renderpass, vk::PipelineLayout& layout, | ||
| 514 | std::tuple<vk::ShaderModule&, vk::ShaderModule&> shaders) { | ||
| 515 | constexpr VkPipelineColorBlendAttachmentState color_blend_attachment_premultiplied{ | ||
| 516 | .blendEnable = VK_TRUE, | ||
| 517 | .srcColorBlendFactor = VK_BLEND_FACTOR_ONE, | ||
| 518 | .dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, | ||
| 519 | .colorBlendOp = VK_BLEND_OP_ADD, | ||
| 520 | .srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE, | ||
| 521 | .dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO, | ||
| 522 | .alphaBlendOp = VK_BLEND_OP_ADD, | ||
| 523 | .colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | | ||
| 524 | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT, | ||
| 525 | }; | ||
| 526 | |||
| 527 | return CreateWrappedPipelineImpl(device, renderpass, layout, shaders, | ||
| 528 | color_blend_attachment_premultiplied); | ||
| 529 | } | ||
| 530 | |||
| 531 | vk::Pipeline CreateWrappedCoverageBlendingPipeline( | ||
| 532 | const Device& device, vk::RenderPass& renderpass, vk::PipelineLayout& layout, | ||
| 533 | std::tuple<vk::ShaderModule&, vk::ShaderModule&> shaders) { | ||
| 534 | constexpr VkPipelineColorBlendAttachmentState color_blend_attachment_coverage{ | ||
| 535 | .blendEnable = VK_TRUE, | ||
| 536 | .srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA, | ||
| 537 | .dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, | ||
| 538 | .colorBlendOp = VK_BLEND_OP_ADD, | ||
| 539 | .srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE, | ||
| 540 | .dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO, | ||
| 541 | .alphaBlendOp = VK_BLEND_OP_ADD, | ||
| 542 | .colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | | ||
| 543 | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT, | ||
| 544 | }; | ||
| 545 | |||
| 546 | return CreateWrappedPipelineImpl(device, renderpass, layout, shaders, | ||
| 547 | color_blend_attachment_coverage); | ||
| 548 | } | ||
| 549 | |||
| 518 | VkWriteDescriptorSet CreateWriteDescriptorSet(std::vector<VkDescriptorImageInfo>& images, | 550 | VkWriteDescriptorSet CreateWriteDescriptorSet(std::vector<VkDescriptorImageInfo>& images, |
| 519 | VkSampler sampler, VkImageView view, | 551 | VkSampler sampler, VkImageView view, |
| 520 | VkDescriptorSet set, u32 binding) { | 552 | VkDescriptorSet set, u32 binding) { |
diff --git a/src/video_core/renderer_vulkan/present/util.h b/src/video_core/renderer_vulkan/present/util.h index 1104aaa15..5b22f0fa8 100644 --- a/src/video_core/renderer_vulkan/present/util.h +++ b/src/video_core/renderer_vulkan/present/util.h | |||
| @@ -42,8 +42,13 @@ vk::PipelineLayout CreateWrappedPipelineLayout(const Device& device, | |||
| 42 | vk::DescriptorSetLayout& layout); | 42 | vk::DescriptorSetLayout& layout); |
| 43 | vk::Pipeline CreateWrappedPipeline(const Device& device, vk::RenderPass& renderpass, | 43 | vk::Pipeline CreateWrappedPipeline(const Device& device, vk::RenderPass& renderpass, |
| 44 | vk::PipelineLayout& layout, | 44 | vk::PipelineLayout& layout, |
| 45 | std::tuple<vk::ShaderModule&, vk::ShaderModule&> shaders, | 45 | std::tuple<vk::ShaderModule&, vk::ShaderModule&> shaders); |
| 46 | bool enable_blending = false); | 46 | vk::Pipeline CreateWrappedPremultipliedBlendingPipeline( |
| 47 | const Device& device, vk::RenderPass& renderpass, vk::PipelineLayout& layout, | ||
| 48 | std::tuple<vk::ShaderModule&, vk::ShaderModule&> shaders); | ||
| 49 | vk::Pipeline CreateWrappedCoverageBlendingPipeline( | ||
| 50 | const Device& device, vk::RenderPass& renderpass, vk::PipelineLayout& layout, | ||
| 51 | std::tuple<vk::ShaderModule&, vk::ShaderModule&> shaders); | ||
| 47 | VkWriteDescriptorSet CreateWriteDescriptorSet(std::vector<VkDescriptorImageInfo>& images, | 52 | VkWriteDescriptorSet CreateWriteDescriptorSet(std::vector<VkDescriptorImageInfo>& images, |
| 48 | VkSampler sampler, VkImageView view, | 53 | VkSampler sampler, VkImageView view, |
| 49 | VkDescriptorSet set, u32 binding); | 54 | VkDescriptorSet set, u32 binding); |
diff --git a/src/video_core/renderer_vulkan/present/window_adapt_pass.cpp b/src/video_core/renderer_vulkan/present/window_adapt_pass.cpp index c5db0230d..22ffacf11 100644 --- a/src/video_core/renderer_vulkan/present/window_adapt_pass.cpp +++ b/src/video_core/renderer_vulkan/present/window_adapt_pass.cpp | |||
| @@ -22,7 +22,7 @@ WindowAdaptPass::WindowAdaptPass(const Device& device_, VkFormat frame_format, | |||
| 22 | CreatePipelineLayout(); | 22 | CreatePipelineLayout(); |
| 23 | CreateVertexShader(); | 23 | CreateVertexShader(); |
| 24 | CreateRenderPass(frame_format); | 24 | CreateRenderPass(frame_format); |
| 25 | CreatePipeline(); | 25 | CreatePipelines(); |
| 26 | } | 26 | } |
| 27 | 27 | ||
| 28 | WindowAdaptPass::~WindowAdaptPass() = default; | 28 | WindowAdaptPass::~WindowAdaptPass() = default; |
| @@ -34,7 +34,6 @@ void WindowAdaptPass::Draw(RasterizerVulkan& rasterizer, Scheduler& scheduler, s | |||
| 34 | 34 | ||
| 35 | const VkFramebuffer host_framebuffer{*dst->framebuffer}; | 35 | const VkFramebuffer host_framebuffer{*dst->framebuffer}; |
| 36 | const VkRenderPass renderpass{*render_pass}; | 36 | const VkRenderPass renderpass{*render_pass}; |
| 37 | const VkPipeline graphics_pipeline{*pipeline}; | ||
| 38 | const VkPipelineLayout graphics_pipeline_layout{*pipeline_layout}; | 37 | const VkPipelineLayout graphics_pipeline_layout{*pipeline_layout}; |
| 39 | const VkExtent2D render_area{ | 38 | const VkExtent2D render_area{ |
| 40 | .width = dst->width, | 39 | .width = dst->width, |
| @@ -44,9 +43,23 @@ void WindowAdaptPass::Draw(RasterizerVulkan& rasterizer, Scheduler& scheduler, s | |||
| 44 | const size_t layer_count = configs.size(); | 43 | const size_t layer_count = configs.size(); |
| 45 | std::vector<PresentPushConstants> push_constants(layer_count); | 44 | std::vector<PresentPushConstants> push_constants(layer_count); |
| 46 | std::vector<VkDescriptorSet> descriptor_sets(layer_count); | 45 | std::vector<VkDescriptorSet> descriptor_sets(layer_count); |
| 46 | std::vector<VkPipeline> graphics_pipelines(layer_count); | ||
| 47 | 47 | ||
| 48 | auto layer_it = layers.begin(); | 48 | auto layer_it = layers.begin(); |
| 49 | for (size_t i = 0; i < layer_count; i++) { | 49 | for (size_t i = 0; i < layer_count; i++) { |
| 50 | switch (configs[i].blending) { | ||
| 51 | case Tegra::BlendMode::Opaque: | ||
| 52 | default: | ||
| 53 | graphics_pipelines[i] = *opaque_pipeline; | ||
| 54 | break; | ||
| 55 | case Tegra::BlendMode::Premultiplied: | ||
| 56 | graphics_pipelines[i] = *premultiplied_pipeline; | ||
| 57 | break; | ||
| 58 | case Tegra::BlendMode::Coverage: | ||
| 59 | graphics_pipelines[i] = *coverage_pipeline; | ||
| 60 | break; | ||
| 61 | } | ||
| 62 | |||
| 50 | layer_it->ConfigureDraw(&push_constants[i], &descriptor_sets[i], rasterizer, *sampler, | 63 | layer_it->ConfigureDraw(&push_constants[i], &descriptor_sets[i], rasterizer, *sampler, |
| 51 | image_index, configs[i], layout); | 64 | image_index, configs[i], layout); |
| 52 | layer_it++; | 65 | layer_it++; |
| @@ -77,8 +90,8 @@ void WindowAdaptPass::Draw(RasterizerVulkan& rasterizer, Scheduler& scheduler, s | |||
| 77 | BeginRenderPass(cmdbuf, renderpass, host_framebuffer, render_area); | 90 | BeginRenderPass(cmdbuf, renderpass, host_framebuffer, render_area); |
| 78 | cmdbuf.ClearAttachments({clear_attachment}, {clear_rect}); | 91 | cmdbuf.ClearAttachments({clear_attachment}, {clear_rect}); |
| 79 | 92 | ||
| 80 | cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, graphics_pipeline); | ||
| 81 | for (size_t i = 0; i < layer_count; i++) { | 93 | for (size_t i = 0; i < layer_count; i++) { |
| 94 | cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, graphics_pipelines[i]); | ||
| 82 | cmdbuf.PushConstants(graphics_pipeline_layout, VK_SHADER_STAGE_VERTEX_BIT, | 95 | cmdbuf.PushConstants(graphics_pipeline_layout, VK_SHADER_STAGE_VERTEX_BIT, |
| 83 | push_constants[i]); | 96 | push_constants[i]); |
| 84 | cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, graphics_pipeline_layout, 0, | 97 | cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, graphics_pipeline_layout, 0, |
| @@ -129,9 +142,13 @@ void WindowAdaptPass::CreateRenderPass(VkFormat frame_format) { | |||
| 129 | render_pass = CreateWrappedRenderPass(device, frame_format, VK_IMAGE_LAYOUT_UNDEFINED); | 142 | render_pass = CreateWrappedRenderPass(device, frame_format, VK_IMAGE_LAYOUT_UNDEFINED); |
| 130 | } | 143 | } |
| 131 | 144 | ||
| 132 | void WindowAdaptPass::CreatePipeline() { | 145 | void WindowAdaptPass::CreatePipelines() { |
| 133 | pipeline = CreateWrappedPipeline(device, render_pass, pipeline_layout, | 146 | opaque_pipeline = CreateWrappedPipeline(device, render_pass, pipeline_layout, |
| 134 | std::tie(vertex_shader, fragment_shader), false); | 147 | std::tie(vertex_shader, fragment_shader)); |
| 148 | premultiplied_pipeline = CreateWrappedPremultipliedBlendingPipeline( | ||
| 149 | device, render_pass, pipeline_layout, std::tie(vertex_shader, fragment_shader)); | ||
| 150 | coverage_pipeline = CreateWrappedCoverageBlendingPipeline( | ||
| 151 | device, render_pass, pipeline_layout, std::tie(vertex_shader, fragment_shader)); | ||
| 135 | } | 152 | } |
| 136 | 153 | ||
| 137 | } // namespace Vulkan | 154 | } // namespace Vulkan |
diff --git a/src/video_core/renderer_vulkan/present/window_adapt_pass.h b/src/video_core/renderer_vulkan/present/window_adapt_pass.h index 0e2edfc31..cf667a4fc 100644 --- a/src/video_core/renderer_vulkan/present/window_adapt_pass.h +++ b/src/video_core/renderer_vulkan/present/window_adapt_pass.h | |||
| @@ -42,7 +42,7 @@ private: | |||
| 42 | void CreatePipelineLayout(); | 42 | void CreatePipelineLayout(); |
| 43 | void CreateVertexShader(); | 43 | void CreateVertexShader(); |
| 44 | void CreateRenderPass(VkFormat frame_format); | 44 | void CreateRenderPass(VkFormat frame_format); |
| 45 | void CreatePipeline(); | 45 | void CreatePipelines(); |
| 46 | 46 | ||
| 47 | private: | 47 | private: |
| 48 | const Device& device; | 48 | const Device& device; |
| @@ -52,7 +52,9 @@ private: | |||
| 52 | vk::ShaderModule vertex_shader; | 52 | vk::ShaderModule vertex_shader; |
| 53 | vk::ShaderModule fragment_shader; | 53 | vk::ShaderModule fragment_shader; |
| 54 | vk::RenderPass render_pass; | 54 | vk::RenderPass render_pass; |
| 55 | vk::Pipeline pipeline; | 55 | vk::Pipeline opaque_pipeline; |
| 56 | vk::Pipeline premultiplied_pipeline; | ||
| 57 | vk::Pipeline coverage_pipeline; | ||
| 56 | }; | 58 | }; |
| 57 | 59 | ||
| 58 | } // namespace Vulkan | 60 | } // namespace Vulkan |
diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp index 48a105327..c7c234fd8 100644 --- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp +++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp | |||
| @@ -101,8 +101,10 @@ RendererVulkan::RendererVulkan(Core::TelemetrySession& telemetry_session_, | |||
| 101 | surface), | 101 | surface), |
| 102 | blit_swapchain(device_memory, device, memory_allocator, present_manager, scheduler), | 102 | blit_swapchain(device_memory, device, memory_allocator, present_manager, scheduler), |
| 103 | blit_screenshot(device_memory, device, memory_allocator, present_manager, scheduler), | 103 | blit_screenshot(device_memory, device, memory_allocator, present_manager, scheduler), |
| 104 | blit_application_layer(device_memory, device, memory_allocator, present_manager, scheduler), | ||
| 104 | rasterizer(render_window, gpu, device_memory, device, memory_allocator, state_tracker, | 105 | rasterizer(render_window, gpu, device_memory, device, memory_allocator, state_tracker, |
| 105 | scheduler) { | 106 | scheduler), |
| 107 | application_frame() { | ||
| 106 | if (Settings::values.renderer_force_max_clock.GetValue() && device.ShouldBoostClocks()) { | 108 | if (Settings::values.renderer_force_max_clock.GetValue() && device.ShouldBoostClocks()) { |
| 107 | turbo_mode.emplace(instance, dld); | 109 | turbo_mode.emplace(instance, dld); |
| 108 | scheduler.RegisterOnSubmit([this] { turbo_mode->QueueSubmitted(); }); | 110 | scheduler.RegisterOnSubmit([this] { turbo_mode->QueueSubmitted(); }); |
diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.h b/src/video_core/renderer_vulkan/renderer_vulkan.h index c6d8a0f21..ed9c7af7f 100644 --- a/src/video_core/renderer_vulkan/renderer_vulkan.h +++ b/src/video_core/renderer_vulkan/renderer_vulkan.h | |||
| @@ -80,8 +80,11 @@ private: | |||
| 80 | PresentManager present_manager; | 80 | PresentManager present_manager; |
| 81 | BlitScreen blit_swapchain; | 81 | BlitScreen blit_swapchain; |
| 82 | BlitScreen blit_screenshot; | 82 | BlitScreen blit_screenshot; |
| 83 | BlitScreen blit_application_layer; | ||
| 83 | RasterizerVulkan rasterizer; | 84 | RasterizerVulkan rasterizer; |
| 84 | std::optional<TurboMode> turbo_mode; | 85 | std::optional<TurboMode> turbo_mode; |
| 86 | |||
| 87 | Frame application_frame; | ||
| 85 | }; | 88 | }; |
| 86 | 89 | ||
| 87 | } // namespace Vulkan | 90 | } // namespace Vulkan |