mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-24 14:49:42 -06:00
Move most backend functionality to VideoCommon
This commit is contained in:
@ -10,64 +10,53 @@
|
||||
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "VideoBackends/Vulkan/Constants.h"
|
||||
#include "VideoBackends/Vulkan/ShaderCache.h"
|
||||
#include "VideoCommon/NativeVertexFormat.h"
|
||||
#include "VideoCommon/RenderBase.h"
|
||||
|
||||
namespace Vulkan
|
||||
{
|
||||
class VKFramebuffer;
|
||||
class VKShader;
|
||||
class VKPipeline;
|
||||
class VKTexture;
|
||||
class StreamBuffer;
|
||||
class VertexFormat;
|
||||
|
||||
class StateTracker
|
||||
{
|
||||
public:
|
||||
StateTracker() = default;
|
||||
~StateTracker() = default;
|
||||
StateTracker();
|
||||
~StateTracker();
|
||||
|
||||
static StateTracker* GetInstance();
|
||||
static bool CreateInstance();
|
||||
static void DestroyInstance();
|
||||
|
||||
VkFramebuffer GetFramebuffer() const { return m_framebuffer; }
|
||||
VKFramebuffer* GetFramebuffer() const { return m_framebuffer; }
|
||||
const VKPipeline* GetPipeline() const { return m_pipeline; }
|
||||
void SetVertexBuffer(VkBuffer buffer, VkDeviceSize offset);
|
||||
void SetIndexBuffer(VkBuffer buffer, VkDeviceSize offset, VkIndexType type);
|
||||
|
||||
void SetRenderPass(VkRenderPass load_render_pass, VkRenderPass clear_render_pass);
|
||||
void SetFramebuffer(VkFramebuffer framebuffer, const VkRect2D& render_area);
|
||||
void SetFramebuffer(VKFramebuffer* framebuffer);
|
||||
void SetPipeline(const VKPipeline* pipeline);
|
||||
|
||||
void UpdateVertexShaderConstants();
|
||||
void UpdateGeometryShaderConstants();
|
||||
void UpdatePixelShaderConstants();
|
||||
|
||||
// Updates constants from external data, e.g. utility draws.
|
||||
void UpdateConstants(const void* data, u32 data_size);
|
||||
|
||||
void SetTexture(size_t index, VkImageView view);
|
||||
void SetSampler(size_t index, VkSampler sampler);
|
||||
|
||||
void SetBBoxBuffer(VkBuffer buffer, VkDeviceSize offset, VkDeviceSize range);
|
||||
void SetComputeShader(const VKShader* shader);
|
||||
void SetGXUniformBuffer(u32 index, VkBuffer buffer, u32 offset, u32 size);
|
||||
void SetUtilityUniformBuffer(VkBuffer buffer, u32 offset, u32 size);
|
||||
void SetTexture(u32 index, VkImageView view);
|
||||
void SetSampler(u32 index, VkSampler sampler);
|
||||
void SetSSBO(VkBuffer buffer, VkDeviceSize offset, VkDeviceSize range);
|
||||
void SetTexelBuffer(u32 index, VkBufferView view);
|
||||
void SetImageTexture(VkImageView view);
|
||||
|
||||
void UnbindTexture(VkImageView view);
|
||||
|
||||
// When executing a command buffer, we want to recreate the descriptor set, as it will
|
||||
// now be in a different pool for the new command buffer.
|
||||
void InvalidateDescriptorSets();
|
||||
|
||||
// Same with the uniforms, as the current storage will belong to the previous command buffer.
|
||||
void InvalidateConstants();
|
||||
|
||||
// Set dirty flags on everything to force re-bind at next draw time.
|
||||
void SetPendingRebind();
|
||||
void InvalidateCachedState();
|
||||
|
||||
// Ends a render pass if we're currently in one.
|
||||
// When Bind() is next called, the pass will be restarted.
|
||||
// Calling this function is allowed even if a pass has not begun.
|
||||
bool InRenderPass() const { return m_current_render_pass != VK_NULL_HANDLE; }
|
||||
void BeginRenderPass();
|
||||
void BeginDiscardRenderPass();
|
||||
void EndRenderPass();
|
||||
|
||||
// Ends the current render pass if it was a clear render pass.
|
||||
@ -78,53 +67,48 @@ public:
|
||||
void SetViewport(const VkViewport& viewport);
|
||||
void SetScissor(const VkRect2D& scissor);
|
||||
|
||||
bool Bind(bool rebind_all = false);
|
||||
// Binds all dirty state to the commmand buffer.
|
||||
// If this returns false, you should not issue the draw.
|
||||
bool Bind();
|
||||
|
||||
// CPU Access Tracking
|
||||
// Call after a draw call is made.
|
||||
void OnDraw();
|
||||
|
||||
// Call after CPU access is requested.
|
||||
void OnCPUEFBAccess();
|
||||
|
||||
// Call after an EFB copy to RAM. If true, the current command buffer should be executed.
|
||||
void OnEFBCopyToRAM();
|
||||
|
||||
// Call at the end of a frame.
|
||||
void OnEndFrame();
|
||||
|
||||
// Prevent/allow background command buffer execution.
|
||||
// Use when queries are active.
|
||||
void SetBackgroundCommandBufferExecution(bool enabled);
|
||||
// Binds all dirty compute state to the command buffer.
|
||||
// If this returns false, you should not dispatch the shader.
|
||||
bool BindCompute();
|
||||
|
||||
// Returns true if the specified rectangle is inside the current render area (used for clears).
|
||||
bool IsWithinRenderArea(s32 x, s32 y, u32 width, u32 height) const;
|
||||
|
||||
private:
|
||||
// Number of descriptor sets for game draws.
|
||||
enum
|
||||
{
|
||||
NUM_GX_DRAW_DESCRIPTOR_SETS = DESCRIPTOR_SET_BIND_POINT_PIXEL_SHADER_SAMPLERS + 1,
|
||||
NUM_GX_DRAW_DESCRIPTOR_SETS_SSBO = DESCRIPTOR_SET_BIND_POINT_STORAGE_OR_TEXEL_BUFFER + 1,
|
||||
NUM_UTILITY_DRAW_DESCRIPTOR_SETS = 2
|
||||
NUM_GX_DESCRIPTOR_SETS = 3,
|
||||
NUM_UTILITY_DESCRIPTOR_SETS = 2,
|
||||
NUM_COMPUTE_DESCRIPTOR_SETS = 1
|
||||
};
|
||||
|
||||
enum DITRY_FLAG : u32
|
||||
enum DIRTY_FLAG : u32
|
||||
{
|
||||
DIRTY_FLAG_VS_UBO = (1 << 0),
|
||||
DIRTY_FLAG_GS_UBO = (1 << 1),
|
||||
DIRTY_FLAG_PS_UBO = (1 << 2),
|
||||
DIRTY_FLAG_PS_SAMPLERS = (1 << 3),
|
||||
DIRTY_FLAG_PS_SSBO = (1 << 4),
|
||||
DIRTY_FLAG_DYNAMIC_OFFSETS = (1 << 5),
|
||||
DIRTY_FLAG_VERTEX_BUFFER = (1 << 6),
|
||||
DIRTY_FLAG_INDEX_BUFFER = (1 << 7),
|
||||
DIRTY_FLAG_VIEWPORT = (1 << 8),
|
||||
DIRTY_FLAG_SCISSOR = (1 << 9),
|
||||
DIRTY_FLAG_PIPELINE = (1 << 10),
|
||||
DIRTY_FLAG_DESCRIPTOR_SET_BINDING = (1 << 11),
|
||||
DIRTY_FLAG_GX_UBOS = (1 << 0),
|
||||
DIRTY_FLAG_GX_UBO_OFFSETS = (1 << 1),
|
||||
DIRTY_FLAG_GX_SAMPLERS = (1 << 4),
|
||||
DIRTY_FLAG_GX_SSBO = (1 << 5),
|
||||
DIRTY_FLAG_UTILITY_UBO = (1 << 2),
|
||||
DIRTY_FLAG_UTILITY_UBO_OFFSET = (1 << 3),
|
||||
DIRTY_FLAG_UTILITY_BINDINGS = (1 << 6),
|
||||
DIRTY_FLAG_COMPUTE_BINDINGS = (1 << 7),
|
||||
DIRTY_FLAG_VERTEX_BUFFER = (1 << 8),
|
||||
DIRTY_FLAG_INDEX_BUFFER = (1 << 9),
|
||||
DIRTY_FLAG_VIEWPORT = (1 << 10),
|
||||
DIRTY_FLAG_SCISSOR = (1 << 11),
|
||||
DIRTY_FLAG_PIPELINE = (1 << 12),
|
||||
DIRTY_FLAG_COMPUTE_SHADER = (1 << 13),
|
||||
DIRTY_FLAG_DESCRIPTOR_SETS = (1 << 14),
|
||||
DIRTY_FLAG_COMPUTE_DESCRIPTOR_SET = (1 << 15),
|
||||
|
||||
DIRTY_FLAG_ALL_DESCRIPTOR_SETS = DIRTY_FLAG_VS_UBO | DIRTY_FLAG_GS_UBO | DIRTY_FLAG_PS_UBO |
|
||||
DIRTY_FLAG_PS_SAMPLERS | DIRTY_FLAG_PS_SSBO
|
||||
DIRTY_FLAG_ALL_DESCRIPTORS = DIRTY_FLAG_GX_UBOS | DIRTY_FLAG_UTILITY_UBO |
|
||||
DIRTY_FLAG_GX_SAMPLERS | DIRTY_FLAG_GX_SSBO |
|
||||
DIRTY_FLAG_UTILITY_BINDINGS | DIRTY_FLAG_COMPUTE_BINDINGS
|
||||
};
|
||||
|
||||
bool Initialize();
|
||||
@ -136,12 +120,7 @@ private:
|
||||
bool UpdateDescriptorSet();
|
||||
bool UpdateGXDescriptorSet();
|
||||
bool UpdateUtilityDescriptorSet();
|
||||
|
||||
// Allocates storage in the uniform buffer of the specified size. If this storage cannot be
|
||||
// allocated immediately, the current command buffer will be submitted and all stage's
|
||||
// constants will be re-uploaded. false will be returned in this case, otherwise true.
|
||||
bool ReserveConstantStorage();
|
||||
void UploadAllConstants();
|
||||
bool UpdateComputeDescriptorSet();
|
||||
|
||||
// Which bindings/state has to be updated before the next draw.
|
||||
u32 m_dirty_flags = 0;
|
||||
@ -155,42 +134,33 @@ private:
|
||||
|
||||
// pipeline state
|
||||
const VKPipeline* m_pipeline = nullptr;
|
||||
const VKShader* m_compute_shader = nullptr;
|
||||
|
||||
// shader bindings
|
||||
std::array<VkDescriptorSet, NUM_DESCRIPTOR_SET_BIND_POINTS> m_descriptor_sets = {};
|
||||
struct
|
||||
{
|
||||
std::array<VkDescriptorBufferInfo, NUM_UBO_DESCRIPTOR_SET_BINDINGS> uniform_buffer_bindings =
|
||||
{};
|
||||
std::array<uint32_t, NUM_UBO_DESCRIPTOR_SET_BINDINGS> uniform_buffer_offsets = {};
|
||||
|
||||
std::array<VkDescriptorImageInfo, NUM_PIXEL_SHADER_SAMPLERS> ps_samplers = {};
|
||||
|
||||
VkDescriptorBufferInfo ps_ssbo = {};
|
||||
} m_bindings;
|
||||
size_t m_uniform_buffer_reserve_size = 0;
|
||||
u32 m_num_active_descriptor_sets = 0;
|
||||
u32 m_num_dynamic_offsets = 0;
|
||||
std::array<VkDescriptorBufferInfo, NUM_UBO_DESCRIPTOR_SET_BINDINGS> gx_ubo_bindings;
|
||||
std::array<u32, NUM_UBO_DESCRIPTOR_SET_BINDINGS> gx_ubo_offsets;
|
||||
VkDescriptorBufferInfo utility_ubo_binding;
|
||||
u32 utility_ubo_offset;
|
||||
std::array<VkDescriptorImageInfo, NUM_PIXEL_SHADER_SAMPLERS> samplers;
|
||||
std::array<VkBufferView, NUM_COMPUTE_TEXEL_BUFFERS> texel_buffers;
|
||||
VkDescriptorBufferInfo ssbo;
|
||||
VkDescriptorImageInfo image_texture;
|
||||
} m_bindings = {};
|
||||
std::array<VkDescriptorSet, NUM_GX_DESCRIPTOR_SETS> m_gx_descriptor_sets = {};
|
||||
std::array<VkDescriptorSet, NUM_UTILITY_DESCRIPTOR_SETS> m_utility_descriptor_sets = {};
|
||||
VkDescriptorSet m_compute_descriptor_set = VK_NULL_HANDLE;
|
||||
|
||||
// rasterization
|
||||
VkViewport m_viewport = {0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f};
|
||||
VkRect2D m_scissor = {{0, 0}, {1, 1}};
|
||||
|
||||
// uniform buffers
|
||||
std::unique_ptr<StreamBuffer> m_uniform_stream_buffer;
|
||||
std::unique_ptr<VKTexture> m_dummy_texture;
|
||||
|
||||
VkFramebuffer m_framebuffer = VK_NULL_HANDLE;
|
||||
VkRenderPass m_load_render_pass = VK_NULL_HANDLE;
|
||||
VkRenderPass m_clear_render_pass = VK_NULL_HANDLE;
|
||||
VKFramebuffer* m_framebuffer = nullptr;
|
||||
VkRenderPass m_current_render_pass = VK_NULL_HANDLE;
|
||||
VkRect2D m_framebuffer_size = {};
|
||||
VkRect2D m_framebuffer_render_area = {};
|
||||
|
||||
// CPU access tracking
|
||||
u32 m_draw_counter = 0;
|
||||
u32 m_last_efb_copy_draw_counter = 0;
|
||||
std::vector<u32> m_cpu_accesses_this_frame;
|
||||
std::vector<u32> m_scheduled_command_buffer_kicks;
|
||||
bool m_allow_background_execution = true;
|
||||
};
|
||||
} // namespace Vulkan
|
||||
|
Reference in New Issue
Block a user