summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Fernando Sahmkow2019-12-30 14:25:14 -0400
committerGravatar GitHub2019-12-30 14:25:14 -0400
commit7bd447355fff63313bef02045a69a88592614bf2 (patch)
treec38d39c40be56d3227204d10f716da994c4275b7 /src
parentMerge pull request #3249 from ReinUsesLisp/vk-staging-buffer-pool (diff)
parentvk_image: Avoid unnecesary equals (diff)
downloadyuzu-7bd447355fff63313bef02045a69a88592614bf2.tar.gz
yuzu-7bd447355fff63313bef02045a69a88592614bf2.tar.xz
yuzu-7bd447355fff63313bef02045a69a88592614bf2.zip
Merge pull request #3248 from ReinUsesLisp/vk-image
vk_image: Add an image object abstraction
Diffstat (limited to 'src')
-rw-r--r--src/video_core/CMakeLists.txt2
-rw-r--r--src/video_core/renderer_vulkan/vk_image.cpp106
-rw-r--r--src/video_core/renderer_vulkan/vk_image.h84
3 files changed, 192 insertions, 0 deletions
diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt
index fcedad3fa..2594cd0bd 100644
--- a/src/video_core/CMakeLists.txt
+++ b/src/video_core/CMakeLists.txt
@@ -159,6 +159,8 @@ if (ENABLE_VULKAN)
159 renderer_vulkan/vk_buffer_cache.h 159 renderer_vulkan/vk_buffer_cache.h
160 renderer_vulkan/vk_device.cpp 160 renderer_vulkan/vk_device.cpp
161 renderer_vulkan/vk_device.h 161 renderer_vulkan/vk_device.h
162 renderer_vulkan/vk_image.cpp
163 renderer_vulkan/vk_image.h
162 renderer_vulkan/vk_memory_manager.cpp 164 renderer_vulkan/vk_memory_manager.cpp
163 renderer_vulkan/vk_memory_manager.h 165 renderer_vulkan/vk_memory_manager.h
164 renderer_vulkan/vk_resource_manager.cpp 166 renderer_vulkan/vk_resource_manager.cpp
diff --git a/src/video_core/renderer_vulkan/vk_image.cpp b/src/video_core/renderer_vulkan/vk_image.cpp
new file mode 100644
index 000000000..4bcbef959
--- /dev/null
+++ b/src/video_core/renderer_vulkan/vk_image.cpp
@@ -0,0 +1,106 @@
1// Copyright 2018 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <memory>
6#include <vector>
7
8#include "common/assert.h"
9#include "video_core/renderer_vulkan/declarations.h"
10#include "video_core/renderer_vulkan/vk_device.h"
11#include "video_core/renderer_vulkan/vk_image.h"
12#include "video_core/renderer_vulkan/vk_scheduler.h"
13
14namespace Vulkan {
15
16VKImage::VKImage(const VKDevice& device, VKScheduler& scheduler,
17 const vk::ImageCreateInfo& image_ci, vk::ImageAspectFlags aspect_mask)
18 : device{device}, scheduler{scheduler}, format{image_ci.format}, aspect_mask{aspect_mask},
19 image_num_layers{image_ci.arrayLayers}, image_num_levels{image_ci.mipLevels} {
20 UNIMPLEMENTED_IF_MSG(image_ci.queueFamilyIndexCount != 0,
21 "Queue family tracking is not implemented");
22
23 const auto dev = device.GetLogical();
24 image = dev.createImageUnique(image_ci, nullptr, device.GetDispatchLoader());
25
26 const u32 num_ranges = image_num_layers * image_num_levels;
27 barriers.resize(num_ranges);
28 subrange_states.resize(num_ranges, {{}, image_ci.initialLayout});
29}
30
31VKImage::~VKImage() = default;
32
33void VKImage::Transition(u32 base_layer, u32 num_layers, u32 base_level, u32 num_levels,
34 vk::PipelineStageFlags new_stage_mask, vk::AccessFlags new_access,
35 vk::ImageLayout new_layout) {
36 if (!HasChanged(base_layer, num_layers, base_level, num_levels, new_access, new_layout)) {
37 return;
38 }
39
40 std::size_t cursor = 0;
41 for (u32 layer_it = 0; layer_it < num_layers; ++layer_it) {
42 for (u32 level_it = 0; level_it < num_levels; ++level_it, ++cursor) {
43 const u32 layer = base_layer + layer_it;
44 const u32 level = base_level + level_it;
45 auto& state = GetSubrangeState(layer, level);
46 barriers[cursor] = vk::ImageMemoryBarrier(
47 state.access, new_access, state.layout, new_layout, VK_QUEUE_FAMILY_IGNORED,
48 VK_QUEUE_FAMILY_IGNORED, *image, {aspect_mask, level, 1, layer, 1});
49 state.access = new_access;
50 state.layout = new_layout;
51 }
52 }
53
54 scheduler.RequestOutsideRenderPassOperationContext();
55
56 scheduler.Record([barriers = barriers, cursor](auto cmdbuf, auto& dld) {
57 // TODO(Rodrigo): Implement a way to use the latest stage across subresources.
58 constexpr auto stage_stub = vk::PipelineStageFlagBits::eAllCommands;
59 cmdbuf.pipelineBarrier(stage_stub, stage_stub, {}, 0, nullptr, 0, nullptr,
60 static_cast<u32>(cursor), barriers.data(), dld);
61 });
62}
63
64bool VKImage::HasChanged(u32 base_layer, u32 num_layers, u32 base_level, u32 num_levels,
65 vk::AccessFlags new_access, vk::ImageLayout new_layout) noexcept {
66 const bool is_full_range = base_layer == 0 && num_layers == image_num_layers &&
67 base_level == 0 && num_levels == image_num_levels;
68 if (!is_full_range) {
69 state_diverged = true;
70 }
71
72 if (!state_diverged) {
73 auto& state = GetSubrangeState(0, 0);
74 if (state.access != new_access || state.layout != new_layout) {
75 return true;
76 }
77 }
78
79 for (u32 layer_it = 0; layer_it < num_layers; ++layer_it) {
80 for (u32 level_it = 0; level_it < num_levels; ++level_it) {
81 const u32 layer = base_layer + layer_it;
82 const u32 level = base_level + level_it;
83 auto& state = GetSubrangeState(layer, level);
84 if (state.access != new_access || state.layout != new_layout) {
85 return true;
86 }
87 }
88 }
89 return false;
90}
91
92void VKImage::CreatePresentView() {
93 // Image type has to be 2D to be presented.
94 const vk::ImageViewCreateInfo image_view_ci({}, *image, vk::ImageViewType::e2D, format, {},
95 {aspect_mask, 0, 1, 0, 1});
96 const auto dev = device.GetLogical();
97 const auto& dld = device.GetDispatchLoader();
98 present_view = dev.createImageViewUnique(image_view_ci, nullptr, dld);
99}
100
101VKImage::SubrangeState& VKImage::GetSubrangeState(u32 layer, u32 level) noexcept {
102 return subrange_states[static_cast<std::size_t>(layer * image_num_levels) +
103 static_cast<std::size_t>(level)];
104}
105
106} // namespace Vulkan \ No newline at end of file
diff --git a/src/video_core/renderer_vulkan/vk_image.h b/src/video_core/renderer_vulkan/vk_image.h
new file mode 100644
index 000000000..b78242512
--- /dev/null
+++ b/src/video_core/renderer_vulkan/vk_image.h
@@ -0,0 +1,84 @@
1// Copyright 2018 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <memory>
8#include <vector>
9
10#include "common/common_types.h"
11#include "video_core/renderer_vulkan/declarations.h"
12
13namespace Vulkan {
14
15class VKDevice;
16class VKScheduler;
17
18class VKImage {
19public:
20 explicit VKImage(const VKDevice& device, VKScheduler& scheduler,
21 const vk::ImageCreateInfo& image_ci, vk::ImageAspectFlags aspect_mask);
22 ~VKImage();
23
24 /// Records in the passed command buffer an image transition and updates the state of the image.
25 void Transition(u32 base_layer, u32 num_layers, u32 base_level, u32 num_levels,
26 vk::PipelineStageFlags new_stage_mask, vk::AccessFlags new_access,
27 vk::ImageLayout new_layout);
28
29 /// Returns a view compatible with presentation, the image has to be 2D.
30 vk::ImageView GetPresentView() {
31 if (!present_view) {
32 CreatePresentView();
33 }
34 return *present_view;
35 }
36
37 /// Returns the Vulkan image handler.
38 vk::Image GetHandle() const {
39 return *image;
40 }
41
42 /// Returns the Vulkan format for this image.
43 vk::Format GetFormat() const {
44 return format;
45 }
46
47 /// Returns the Vulkan aspect mask.
48 vk::ImageAspectFlags GetAspectMask() const {
49 return aspect_mask;
50 }
51
52private:
53 struct SubrangeState final {
54 vk::AccessFlags access{}; ///< Current access bits.
55 vk::ImageLayout layout = vk::ImageLayout::eUndefined; ///< Current image layout.
56 };
57
58 bool HasChanged(u32 base_layer, u32 num_layers, u32 base_level, u32 num_levels,
59 vk::AccessFlags new_access, vk::ImageLayout new_layout) noexcept;
60
61 /// Creates a presentation view.
62 void CreatePresentView();
63
64 /// Returns the subrange state for a layer and layer.
65 SubrangeState& GetSubrangeState(u32 layer, u32 level) noexcept;
66
67 const VKDevice& device; ///< Device handler.
68 VKScheduler& scheduler; ///< Device scheduler.
69
70 const vk::Format format; ///< Vulkan format.
71 const vk::ImageAspectFlags aspect_mask; ///< Vulkan aspect mask.
72 const u32 image_num_layers; ///< Number of layers.
73 const u32 image_num_levels; ///< Number of mipmap levels.
74
75 UniqueImage image; ///< Image handle.
76 UniqueImageView present_view; ///< Image view compatible with presentation.
77
78 std::vector<vk::ImageMemoryBarrier> barriers; ///< Pool of barriers.
79 std::vector<SubrangeState> subrange_states; ///< Current subrange state.
80
81 bool state_diverged = false; ///< True when subresources mismatch in layout.
82};
83
84} // namespace Vulkan