[Vulkan] Basic draw call architecture + [D3D12] Some cleanup
This commit is contained in:
@@ -10,6 +10,7 @@
|
||||
#ifndef XENIA_GPU_VULKAN_VULKAN_COMMAND_PROCESSOR_H_
|
||||
#define XENIA_GPU_VULKAN_VULKAN_COMMAND_PROCESSOR_H_
|
||||
|
||||
#include <climits>
|
||||
#include <cstdint>
|
||||
#include <deque>
|
||||
#include <memory>
|
||||
@@ -18,13 +19,18 @@
|
||||
#include <vector>
|
||||
|
||||
#include "xenia/gpu/command_processor.h"
|
||||
#include "xenia/gpu/spirv_shader_translator.h"
|
||||
#include "xenia/gpu/vulkan/deferred_command_buffer.h"
|
||||
#include "xenia/gpu/vulkan/vulkan_graphics_system.h"
|
||||
#include "xenia/gpu/vulkan/vulkan_pipeline_cache.h"
|
||||
#include "xenia/gpu/vulkan/vulkan_render_target_cache.h"
|
||||
#include "xenia/gpu/vulkan/vulkan_shader.h"
|
||||
#include "xenia/gpu/vulkan/vulkan_shared_memory.h"
|
||||
#include "xenia/gpu/xenos.h"
|
||||
#include "xenia/kernel/kernel_state.h"
|
||||
#include "xenia/ui/vulkan/transient_descriptor_pool.h"
|
||||
#include "xenia/ui/vulkan/vulkan_context.h"
|
||||
#include "xenia/ui/vulkan/vulkan_upload_buffer_pool.h"
|
||||
|
||||
namespace xe {
|
||||
namespace gpu {
|
||||
@@ -67,19 +73,21 @@ class VulkanCommandProcessor : public CommandProcessor {
|
||||
const VkSparseMemoryBind* binds,
|
||||
VkPipelineStageFlags wait_stage_mask);
|
||||
|
||||
struct PipelineLayout {
|
||||
VkPipelineLayout pipeline_layout;
|
||||
VkDescriptorSetLayout descriptor_set_layout_textures_pixel_ref;
|
||||
VkDescriptorSetLayout descriptor_set_layout_textures_vertex_ref;
|
||||
};
|
||||
bool GetPipelineLayout(uint32_t texture_count_pixel,
|
||||
uint32_t texture_count_vertex,
|
||||
PipelineLayout& pipeline_layout_out);
|
||||
// Must be called before doing anything outside the render pass scope,
|
||||
// including adding pipeline barriers that are not a part of the render pass
|
||||
// scope. Submission must be open.
|
||||
void EndRenderPass();
|
||||
|
||||
// The returned reference is valid until a cache clear.
|
||||
const VulkanPipelineCache::PipelineLayoutProvider* GetPipelineLayout(
|
||||
uint32_t texture_count_pixel, uint32_t texture_count_vertex);
|
||||
|
||||
protected:
|
||||
bool SetupContext() override;
|
||||
void ShutdownContext() override;
|
||||
|
||||
void WriteRegister(uint32_t index, uint32_t value) override;
|
||||
|
||||
void PerformSwap(uint32_t frontbuffer_ptr, uint32_t frontbuffer_width,
|
||||
uint32_t frontbuffer_height) override;
|
||||
|
||||
@@ -95,6 +103,49 @@ class VulkanCommandProcessor : public CommandProcessor {
|
||||
void InitializeTrace() override;
|
||||
|
||||
private:
|
||||
struct CommandBuffer {
|
||||
VkCommandPool pool;
|
||||
VkCommandBuffer buffer;
|
||||
};
|
||||
|
||||
struct SparseBufferBind {
|
||||
VkBuffer buffer;
|
||||
size_t bind_offset;
|
||||
uint32_t bind_count;
|
||||
};
|
||||
|
||||
union TextureDescriptorSetLayoutKey {
|
||||
struct {
|
||||
uint32_t is_vertex : 1;
|
||||
// For 0, use descriptor_set_layout_empty_ instead as these are owning
|
||||
// references.
|
||||
uint32_t texture_count : 31;
|
||||
};
|
||||
uint32_t key = 0;
|
||||
};
|
||||
static_assert(sizeof(TextureDescriptorSetLayoutKey) == sizeof(uint32_t));
|
||||
|
||||
union PipelineLayoutKey {
|
||||
struct {
|
||||
// Pixel textures in the low bits since those are varied much more
|
||||
// commonly.
|
||||
uint32_t texture_count_pixel : 16;
|
||||
uint32_t texture_count_vertex : 16;
|
||||
};
|
||||
uint32_t key = 0;
|
||||
};
|
||||
static_assert(sizeof(PipelineLayoutKey) == sizeof(uint32_t));
|
||||
|
||||
class PipelineLayout : public VulkanPipelineCache::PipelineLayoutProvider {
|
||||
public:
|
||||
VkPipelineLayout GetPipelineLayout() const override {
|
||||
return pipeline_layout;
|
||||
}
|
||||
VkPipelineLayout pipeline_layout;
|
||||
VkDescriptorSetLayout descriptor_set_layout_textures_pixel_ref;
|
||||
VkDescriptorSetLayout descriptor_set_layout_textures_vertex_ref;
|
||||
};
|
||||
|
||||
// BeginSubmission and EndSubmission may be called at any time. If there's an
|
||||
// open non-frame submission, BeginSubmission(true) will promote it to a
|
||||
// frame. EndSubmission(true) will close the frame no matter whether the
|
||||
@@ -119,6 +170,18 @@ class VulkanCommandProcessor : public CommandProcessor {
|
||||
|
||||
VkShaderStageFlags GetGuestVertexShaderStageFlags() const;
|
||||
|
||||
void UpdateFixedFunctionState();
|
||||
void UpdateSystemConstantValues(xenos::Endian index_endian);
|
||||
bool UpdateBindings(const VulkanShader* vertex_shader,
|
||||
const VulkanShader* pixel_shader);
|
||||
// Allocates a descriptor, space in the uniform buffer pool, and fills the
|
||||
// VkWriteDescriptorSet structure and VkDescriptorBufferInfo referenced by it.
|
||||
// Returns null in case of failure.
|
||||
uint8_t* WriteUniformBufferBinding(
|
||||
size_t size, VkDescriptorSetLayout descriptor_set_layout,
|
||||
VkDescriptorBufferInfo& descriptor_buffer_info_out,
|
||||
VkWriteDescriptorSet& write_descriptor_set_out);
|
||||
|
||||
bool cache_clear_requested_ = false;
|
||||
|
||||
std::vector<VkFence> fences_free_;
|
||||
@@ -143,20 +206,11 @@ class VulkanCommandProcessor : public CommandProcessor {
|
||||
// Submission indices of frames that have already been submitted.
|
||||
uint64_t closed_frame_submissions_[kMaxFramesInFlight] = {};
|
||||
|
||||
struct CommandBuffer {
|
||||
VkCommandPool pool;
|
||||
VkCommandBuffer buffer;
|
||||
};
|
||||
std::vector<CommandBuffer> command_buffers_writable_;
|
||||
std::deque<std::pair<CommandBuffer, uint64_t>> command_buffers_submitted_;
|
||||
DeferredCommandBuffer deferred_command_buffer_;
|
||||
|
||||
std::vector<VkSparseMemoryBind> sparse_memory_binds_;
|
||||
struct SparseBufferBind {
|
||||
VkBuffer buffer;
|
||||
size_t bind_offset;
|
||||
uint32_t bind_count;
|
||||
};
|
||||
std::vector<SparseBufferBind> sparse_buffer_binds_;
|
||||
// SparseBufferBind converted to VkSparseBufferMemoryBindInfo to this buffer
|
||||
// on submission (because pBinds should point to a place in std::vector, but
|
||||
@@ -166,6 +220,7 @@ class VulkanCommandProcessor : public CommandProcessor {
|
||||
|
||||
std::unique_ptr<ui::vulkan::TransientDescriptorPool>
|
||||
transient_descriptor_pool_uniform_buffers_;
|
||||
std::unique_ptr<ui::vulkan::VulkanUploadBufferPool> uniform_buffer_pool_;
|
||||
|
||||
// Descriptor set layouts used by different shaders.
|
||||
VkDescriptorSetLayout descriptor_set_layout_empty_ = VK_NULL_HANDLE;
|
||||
@@ -180,34 +235,66 @@ class VulkanCommandProcessor : public CommandProcessor {
|
||||
VkDescriptorSetLayout descriptor_set_layout_shared_memory_and_edram_ =
|
||||
VK_NULL_HANDLE;
|
||||
|
||||
union TextureDescriptorSetLayoutKey {
|
||||
struct {
|
||||
uint32_t is_vertex : 1;
|
||||
// For 0, use descriptor_set_layout_empty_ instead as these are owning
|
||||
// references.
|
||||
uint32_t texture_count : 31;
|
||||
};
|
||||
uint32_t key = 0;
|
||||
};
|
||||
// TextureDescriptorSetLayoutKey::key -> VkDescriptorSetLayout.
|
||||
// Layouts are referenced by pipeline_layouts_.
|
||||
std::unordered_map<uint32_t, VkDescriptorSetLayout>
|
||||
descriptor_set_layouts_textures_;
|
||||
union PipelineLayoutKey {
|
||||
struct {
|
||||
// Pixel textures in the low bits since those are varied much more
|
||||
// commonly.
|
||||
uint32_t texture_count_pixel : 16;
|
||||
uint32_t texture_count_vertex : 16;
|
||||
};
|
||||
uint32_t key = 0;
|
||||
};
|
||||
// PipelineLayoutKey::key -> PipelineLayout.
|
||||
// Layouts are referenced by VulkanPipelineCache.
|
||||
std::unordered_map<uint32_t, PipelineLayout> pipeline_layouts_;
|
||||
|
||||
std::unique_ptr<VulkanSharedMemory> shared_memory_;
|
||||
|
||||
std::unique_ptr<VulkanPipelineCache> pipeline_cache_;
|
||||
|
||||
std::unique_ptr<VulkanRenderTargetCache> render_target_cache_;
|
||||
|
||||
VkDescriptorPool shared_memory_and_edram_descriptor_pool_ = VK_NULL_HANDLE;
|
||||
VkDescriptorSet shared_memory_and_edram_descriptor_set_;
|
||||
|
||||
// The current fixed-function drawing state.
|
||||
VkViewport ff_viewport_;
|
||||
VkRect2D ff_scissor_;
|
||||
bool ff_viewport_update_needed_;
|
||||
bool ff_scissor_update_needed_;
|
||||
|
||||
// Cache render pass currently started in the command buffer with framebuffer.
|
||||
VkRenderPass current_render_pass_;
|
||||
VkFramebuffer current_framebuffer_;
|
||||
|
||||
// Cache graphics pipeline currently bound to the command buffer.
|
||||
VkPipeline current_graphics_pipeline_;
|
||||
|
||||
// Pipeline layout of the current graphics pipeline.
|
||||
const PipelineLayout* current_graphics_pipeline_layout_;
|
||||
VkDescriptorSet current_graphics_descriptor_sets_
|
||||
[SpirvShaderTranslator::kDescriptorSetCount];
|
||||
// Whether descriptor sets in current_graphics_descriptor_sets_ point to
|
||||
// up-to-date data.
|
||||
uint32_t current_graphics_descriptor_set_values_up_to_date_;
|
||||
// Whether the descriptor sets currently bound to the command buffer - only
|
||||
// low bits for the descriptor set layouts that remained the same are kept
|
||||
// when changing the pipeline layout. May be out of sync with
|
||||
// current_graphics_descriptor_set_values_up_to_date_, but should be ensured
|
||||
// to be a subset of it at some point when it becomes important; bits for
|
||||
// non-existent descriptor set layouts may also be set, but need to be ignored
|
||||
// when they start to matter.
|
||||
uint32_t current_graphics_descriptor_sets_bound_up_to_date_;
|
||||
static_assert(
|
||||
SpirvShaderTranslator::kDescriptorSetCount <=
|
||||
sizeof(current_graphics_descriptor_set_values_up_to_date_) * CHAR_BIT,
|
||||
"Bit fields storing descriptor set validity must be large enough");
|
||||
static_assert(
|
||||
SpirvShaderTranslator::kDescriptorSetCount <=
|
||||
sizeof(current_graphics_descriptor_sets_bound_up_to_date_) * CHAR_BIT,
|
||||
"Bit fields storing descriptor set validity must be large enough");
|
||||
|
||||
// Float constant usage masks of the last draw call.
|
||||
uint64_t current_float_constant_map_vertex_[4];
|
||||
uint64_t current_float_constant_map_pixel_[4];
|
||||
|
||||
// System shader constants.
|
||||
SpirvShaderTranslator::SystemConstants system_constants_;
|
||||
};
|
||||
|
||||
} // namespace vulkan
|
||||
|
||||
Reference in New Issue
Block a user