1 // Copyright 2016 Dolphin Emulator Project 2 // Licensed under GPLv2+ 3 // Refer to the license.txt file included. 4 5 #pragma once 6 7 #include <array> 8 #include <cstddef> 9 #include <memory> 10 11 #include "Common/CommonTypes.h" 12 #include "VideoBackends/Vulkan/Constants.h" 13 #include "VideoCommon/RenderBase.h" 14 15 namespace Vulkan 16 { 17 class VKFramebuffer; 18 class VKShader; 19 class VKPipeline; 20 class VKTexture; 21 class StreamBuffer; 22 class VertexFormat; 23 24 class StateTracker 25 { 26 public: 27 StateTracker(); 28 ~StateTracker(); 29 30 static StateTracker* GetInstance(); 31 static bool CreateInstance(); 32 static void DestroyInstance(); 33 GetFramebuffer()34 VKFramebuffer* GetFramebuffer() const { return m_framebuffer; } GetPipeline()35 const VKPipeline* GetPipeline() const { return m_pipeline; } 36 void SetVertexBuffer(VkBuffer buffer, VkDeviceSize offset); 37 void SetIndexBuffer(VkBuffer buffer, VkDeviceSize offset, VkIndexType type); 38 void SetFramebuffer(VKFramebuffer* framebuffer); 39 void SetPipeline(const VKPipeline* pipeline); 40 void SetComputeShader(const VKShader* shader); 41 void SetGXUniformBuffer(u32 index, VkBuffer buffer, u32 offset, u32 size); 42 void SetUtilityUniformBuffer(VkBuffer buffer, u32 offset, u32 size); 43 void SetTexture(u32 index, VkImageView view); 44 void SetSampler(u32 index, VkSampler sampler); 45 void SetSSBO(VkBuffer buffer, VkDeviceSize offset, VkDeviceSize range); 46 void SetTexelBuffer(u32 index, VkBufferView view); 47 void SetImageTexture(VkImageView view); 48 49 void UnbindTexture(VkImageView view); 50 51 // Set dirty flags on everything to force re-bind at next draw time. 52 void InvalidateCachedState(); 53 54 // Ends a render pass if we're currently in one. 55 // When Bind() is next called, the pass will be restarted. 56 // Calling this function is allowed even if a pass has not begun. InRenderPass()57 bool InRenderPass() const { return m_current_render_pass != VK_NULL_HANDLE; } 58 void BeginRenderPass(); 59 void BeginDiscardRenderPass(); 60 void EndRenderPass(); 61 62 // Ends the current render pass if it was a clear render pass. 63 void BeginClearRenderPass(const VkRect2D& area, const VkClearValue* clear_values, 64 u32 num_clear_values); 65 void EndClearRenderPass(); 66 67 void SetViewport(const VkViewport& viewport); 68 void SetScissor(const VkRect2D& scissor); 69 70 // Binds all dirty state to the commmand buffer. 71 // If this returns false, you should not issue the draw. 72 bool Bind(); 73 74 // Binds all dirty compute state to the command buffer. 75 // If this returns false, you should not dispatch the shader. 76 bool BindCompute(); 77 78 // Returns true if the specified rectangle is inside the current render area (used for clears). 79 bool IsWithinRenderArea(s32 x, s32 y, u32 width, u32 height) const; 80 81 private: 82 // Number of descriptor sets for game draws. 83 enum 84 { 85 NUM_GX_DESCRIPTOR_SETS = 3, 86 NUM_UTILITY_DESCRIPTOR_SETS = 2, 87 NUM_COMPUTE_DESCRIPTOR_SETS = 1 88 }; 89 90 enum DIRTY_FLAG : u32 91 { 92 DIRTY_FLAG_GX_UBOS = (1 << 0), 93 DIRTY_FLAG_GX_UBO_OFFSETS = (1 << 1), 94 DIRTY_FLAG_GX_SAMPLERS = (1 << 4), 95 DIRTY_FLAG_GX_SSBO = (1 << 5), 96 DIRTY_FLAG_UTILITY_UBO = (1 << 2), 97 DIRTY_FLAG_UTILITY_UBO_OFFSET = (1 << 3), 98 DIRTY_FLAG_UTILITY_BINDINGS = (1 << 6), 99 DIRTY_FLAG_COMPUTE_BINDINGS = (1 << 7), 100 DIRTY_FLAG_VERTEX_BUFFER = (1 << 8), 101 DIRTY_FLAG_INDEX_BUFFER = (1 << 9), 102 DIRTY_FLAG_VIEWPORT = (1 << 10), 103 DIRTY_FLAG_SCISSOR = (1 << 11), 104 DIRTY_FLAG_PIPELINE = (1 << 12), 105 DIRTY_FLAG_COMPUTE_SHADER = (1 << 13), 106 DIRTY_FLAG_DESCRIPTOR_SETS = (1 << 14), 107 DIRTY_FLAG_COMPUTE_DESCRIPTOR_SET = (1 << 15), 108 109 DIRTY_FLAG_ALL_DESCRIPTORS = DIRTY_FLAG_GX_UBOS | DIRTY_FLAG_UTILITY_UBO | 110 DIRTY_FLAG_GX_SAMPLERS | DIRTY_FLAG_GX_SSBO | 111 DIRTY_FLAG_UTILITY_BINDINGS | DIRTY_FLAG_COMPUTE_BINDINGS 112 }; 113 114 bool Initialize(); 115 116 // Check that the specified viewport is within the render area. 117 // If not, ends the render pass if it is a clear render pass. 118 bool IsViewportWithinRenderArea() const; 119 120 bool UpdateDescriptorSet(); 121 bool UpdateGXDescriptorSet(); 122 bool UpdateUtilityDescriptorSet(); 123 bool UpdateComputeDescriptorSet(); 124 125 // Which bindings/state has to be updated before the next draw. 126 u32 m_dirty_flags = 0; 127 128 // input assembly 129 VkBuffer m_vertex_buffer = VK_NULL_HANDLE; 130 VkDeviceSize m_vertex_buffer_offset = 0; 131 VkBuffer m_index_buffer = VK_NULL_HANDLE; 132 VkDeviceSize m_index_buffer_offset = 0; 133 VkIndexType m_index_type = VK_INDEX_TYPE_UINT16; 134 135 // pipeline state 136 const VKPipeline* m_pipeline = nullptr; 137 const VKShader* m_compute_shader = nullptr; 138 139 // shader bindings 140 struct 141 { 142 std::array<VkDescriptorBufferInfo, NUM_UBO_DESCRIPTOR_SET_BINDINGS> gx_ubo_bindings; 143 std::array<u32, NUM_UBO_DESCRIPTOR_SET_BINDINGS> gx_ubo_offsets; 144 VkDescriptorBufferInfo utility_ubo_binding; 145 u32 utility_ubo_offset; 146 std::array<VkDescriptorImageInfo, NUM_PIXEL_SHADER_SAMPLERS> samplers; 147 std::array<VkBufferView, NUM_COMPUTE_TEXEL_BUFFERS> texel_buffers; 148 VkDescriptorBufferInfo ssbo; 149 VkDescriptorImageInfo image_texture; 150 } m_bindings = {}; 151 std::array<VkDescriptorSet, NUM_GX_DESCRIPTOR_SETS> m_gx_descriptor_sets = {}; 152 std::array<VkDescriptorSet, NUM_UTILITY_DESCRIPTOR_SETS> m_utility_descriptor_sets = {}; 153 VkDescriptorSet m_compute_descriptor_set = VK_NULL_HANDLE; 154 155 // rasterization 156 VkViewport m_viewport = {0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f}; 157 VkRect2D m_scissor = {{0, 0}, {1, 1}}; 158 159 // uniform buffers 160 std::unique_ptr<VKTexture> m_dummy_texture; 161 162 VKFramebuffer* m_framebuffer = nullptr; 163 VkRenderPass m_current_render_pass = VK_NULL_HANDLE; 164 VkRect2D m_framebuffer_render_area = {}; 165 }; 166 } // namespace Vulkan 167