summaryrefslogtreecommitdiff
path: root/Source/Core/VideoCommon
diff options
context:
space:
mode:
authorPierre Bourdon <delroth@gmail.com>2018-12-04 08:47:46 +0100
committerGitHub <noreply@github.com>2018-12-04 08:47:46 +0100
commit59de8ea50338b39f604fde738229aaeb791cc459 (patch)
tree17f445fc7a686cd28859e6c46fb1a32d64a56123 /Source/Core/VideoCommon
parentc675ef148e6872115bd46cca5b5c51826c75b373 (diff)
parent7afd5cc2fb7e45f2c497e5aed007a017b8461335 (diff)
Merge pull request #7592 from stenzek/imgui-prereq
VideoBackends: Share GX vertex/index/uniform buffers with utility draws
Diffstat (limited to 'Source/Core/VideoCommon')
-rw-r--r--Source/Core/VideoCommon/IndexGenerator.cpp8
-rw-r--r--Source/Core/VideoCommon/IndexGenerator.h2
-rw-r--r--Source/Core/VideoCommon/RenderBase.cpp16
-rw-r--r--Source/Core/VideoCommon/RenderBase.h23
-rw-r--r--Source/Core/VideoCommon/VertexManagerBase.cpp58
-rw-r--r--Source/Core/VideoCommon/VertexManagerBase.h28
6 files changed, 104 insertions, 31 deletions
diff --git a/Source/Core/VideoCommon/IndexGenerator.cpp b/Source/Core/VideoCommon/IndexGenerator.cpp
index 6cb49aceba..5e45cc6a5f 100644
--- a/Source/Core/VideoCommon/IndexGenerator.cpp
+++ b/Source/Core/VideoCommon/IndexGenerator.cpp
@@ -3,6 +3,7 @@
// Refer to the license.txt file included.
#include <cstddef>
+#include <cstring>
#include "Common/CommonTypes.h"
#include "Common/Compiler.h"
@@ -56,6 +57,13 @@ void IndexGenerator::AddIndices(int primitive, u32 numVerts)
base_index += numVerts;
}
+void IndexGenerator::AddExternalIndices(const u16* indices, u32 num_indices, u32 num_vertices)
+{
+ std::memcpy(index_buffer_current, indices, sizeof(u16) * num_indices);
+ index_buffer_current += num_indices;
+ base_index += num_vertices;
+}
+
// Triangles
template <bool pr>
DOLPHIN_FORCE_INLINE u16* IndexGenerator::WriteTriangle(u16* Iptr, u32 index1, u32 index2,
diff --git a/Source/Core/VideoCommon/IndexGenerator.h b/Source/Core/VideoCommon/IndexGenerator.h
index 8d2a5e8700..67f16b66c1 100644
--- a/Source/Core/VideoCommon/IndexGenerator.h
+++ b/Source/Core/VideoCommon/IndexGenerator.h
@@ -18,6 +18,8 @@ public:
static void AddIndices(int primitive, u32 numVertices);
+ static void AddExternalIndices(const u16* indices, u32 num_indices, u32 num_vertices);
+
// returns numprimitives
static u32 GetNumVerts() { return base_index; }
static u32 GetIndexLen() { return (u32)(index_buffer_current - BASEIptr); }
diff --git a/Source/Core/VideoCommon/RenderBase.cpp b/Source/Core/VideoCommon/RenderBase.cpp
index 2e42ed984a..ba60e1636c 100644
--- a/Source/Core/VideoCommon/RenderBase.cpp
+++ b/Source/Core/VideoCommon/RenderBase.cpp
@@ -78,8 +78,10 @@ static float AspectToWidescreen(float aspect)
return aspect * ((16.0f / 9.0f) / (4.0f / 3.0f));
}
-Renderer::Renderer(int backbuffer_width, int backbuffer_height)
- : m_backbuffer_width(backbuffer_width), m_backbuffer_height(backbuffer_height)
+Renderer::Renderer(int backbuffer_width, int backbuffer_height,
+ AbstractTextureFormat backbuffer_format)
+ : m_backbuffer_width(backbuffer_width), m_backbuffer_height(backbuffer_height),
+ m_backbuffer_format(backbuffer_format)
{
UpdateActiveConfig();
UpdateDrawRectangle();
@@ -93,6 +95,11 @@ Renderer::Renderer(int backbuffer_width, int backbuffer_height)
Renderer::~Renderer() = default;
+bool Renderer::Initialize()
+{
+ return true;
+}
+
void Renderer::Shutdown()
{
// First stop any framedumping, which might need to dump the last xfb frame. This process
@@ -697,6 +704,11 @@ void Renderer::Swap(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, const
m_last_xfb_region = xfb_rect;
+ // Since we use the common pipelines here and draw vertices if a batch is currently being
+ // built by the vertex loader, we end up trampling over its pointer, as we share the buffer
+ // with the loader, and it has not been unmapped yet. Force a pipeline flush to avoid this.
+ g_vertex_manager->Flush();
+
// TODO: merge more generic parts into VideoCommon
{
std::lock_guard<std::mutex> guard(m_swap_mutex);
diff --git a/Source/Core/VideoCommon/RenderBase.h b/Source/Core/VideoCommon/RenderBase.h
index d5dd761c40..bea1f5ba0a 100644
--- a/Source/Core/VideoCommon/RenderBase.h
+++ b/Source/Core/VideoCommon/RenderBase.h
@@ -32,6 +32,7 @@
#include "VideoCommon/BPMemory.h"
#include "VideoCommon/FPSCounter.h"
#include "VideoCommon/RenderState.h"
+#include "VideoCommon/TextureConfig.h"
#include "VideoCommon/VideoCommon.h"
class AbstractFramebuffer;
@@ -72,13 +73,16 @@ enum class OSDMessage : s32
class Renderer
{
public:
- Renderer(int backbuffer_width, int backbuffer_height);
+ Renderer(int backbuffer_width, int backbuffer_height, AbstractTextureFormat backbuffer_format);
virtual ~Renderer();
using ClearColor = std::array<float, 4>;
virtual bool IsHeadless() const = 0;
+ virtual bool Initialize();
+ virtual void Shutdown();
+
virtual void SetPipeline(const AbstractPipeline* pipeline) {}
virtual void SetScissorRect(const MathUtil::Rectangle<int>& rc) {}
virtual void SetTexture(u32 index, const AbstractTexture* texture) {}
@@ -110,6 +114,10 @@ public:
{
}
+ // Drawing with currently-bound pipeline state.
+ virtual void Draw(u32 base_vertex, u32 num_vertices) {}
+ virtual void DrawIndexed(u32 base_index, u32 num_indices, u32 base_vertex) {}
+
// Shader modules/objects.
virtual std::unique_ptr<AbstractShader>
CreateShaderFromSource(ShaderStage stage, const char* source, size_t length) = 0;
@@ -188,18 +196,6 @@ public:
virtual std::unique_ptr<VideoCommon::AsyncShaderCompiler> CreateAsyncShaderCompiler();
- virtual void Shutdown();
-
- // Drawing utility shaders.
- virtual void DrawUtilityPipeline(const void* uniforms, u32 uniforms_size, const void* vertices,
- u32 vertex_stride, u32 num_vertices)
- {
- }
- virtual void DispatchComputeShader(const AbstractShader* shader, const void* uniforms,
- u32 uniforms_size, u32 groups_x, u32 groups_y, u32 groups_z)
- {
- }
-
void ShowOSDMessage(OSDMessage message);
protected:
@@ -229,6 +225,7 @@ protected:
// Backbuffer (window) size and render area
int m_backbuffer_width = 0;
int m_backbuffer_height = 0;
+ AbstractTextureFormat m_backbuffer_format = AbstractTextureFormat::Undefined;
TargetRectangle m_target_rectangle = {};
FPSCounter m_fps_counter;
diff --git a/Source/Core/VideoCommon/VertexManagerBase.cpp b/Source/Core/VideoCommon/VertexManagerBase.cpp
index 8364b039c5..0e178e4d9b 100644
--- a/Source/Core/VideoCommon/VertexManagerBase.cpp
+++ b/Source/Core/VideoCommon/VertexManagerBase.cpp
@@ -27,6 +27,7 @@
#include "VideoCommon/PixelShaderManager.h"
#include "VideoCommon/RenderBase.h"
#include "VideoCommon/SamplerCommon.h"
+#include "VideoCommon/Statistics.h"
#include "VideoCommon/TextureCacheBase.h"
#include "VideoCommon/VertexLoaderManager.h"
#include "VideoCommon/VertexShaderManager.h"
@@ -131,7 +132,7 @@ DataReader VertexManagerBase::PrepareForAdditionalData(int primitive, u32 count,
// need to alloc new buffer
if (m_is_flushed)
{
- g_vertex_manager->ResetBuffer(stride);
+ g_vertex_manager->ResetBuffer(stride, cullall);
m_is_flushed = false;
}
@@ -209,6 +210,28 @@ std::pair<size_t, size_t> VertexManagerBase::ResetFlushAspectRatioCount()
return val;
}
+void VertexManagerBase::UploadUtilityVertices(const void* vertices, u32 vertex_stride,
+ u32 num_vertices, const u16* indices, u32 num_indices,
+ u32* out_base_vertex, u32* out_base_index)
+{
+ // The GX vertex list should be flushed before any utility draws occur.
+ ASSERT(m_is_flushed);
+
+ // Copy into the buffers usually used for GX drawing.
+ ResetBuffer(std::max(vertex_stride, 1u), false);
+ if (vertices)
+ {
+ const u32 copy_size = vertex_stride * num_vertices;
+ ASSERT((m_cur_buffer_pointer + copy_size) <= m_end_buffer_pointer);
+ std::memcpy(m_cur_buffer_pointer, vertices, copy_size);
+ m_cur_buffer_pointer += copy_size;
+ }
+ if (indices)
+ IndexGenerator::AddExternalIndices(indices, num_indices, num_vertices);
+
+ CommitBuffer(num_vertices, vertex_stride, num_indices, out_base_vertex, out_base_index);
+}
+
static void SetSamplerState(u32 index, float custom_tex_scale, bool custom_tex,
bool has_arbitrary_mips)
{
@@ -384,19 +407,35 @@ void VertexManagerBase::Flush()
if (!m_cull_all)
{
+ // Update and upload constants. Note for the Vulkan backend, this must occur before the
+ // vertex/index buffer is committed, otherwise the data will be associated with the
+ // previous command buffer, instead of the one with the draw if there is an overflow.
+ GeometryShaderManager::SetConstants();
+ PixelShaderManager::SetConstants();
+ UploadConstants();
+
+ // Now the vertices can be flushed to the GPU.
+ const u32 num_indices = IndexGenerator::GetIndexLen();
+ u32 base_vertex, base_index;
+ CommitBuffer(IndexGenerator::GetNumVerts(),
+ VertexLoaderManager::GetCurrentVertexFormat()->GetVertexStride(), num_indices,
+ &base_vertex, &base_index);
+
// Update the pipeline, or compile one if needed.
UpdatePipelineConfig();
UpdatePipelineObject();
+ if (m_current_pipeline_object)
+ {
+ g_renderer->SetPipeline(m_current_pipeline_object);
+ if (PerfQueryBase::ShouldEmulate())
+ g_perf_query->EnableQuery(bpmem.zcontrol.early_ztest ? PQG_ZCOMP_ZCOMPLOC : PQG_ZCOMP);
- // set the rest of the global constants
- GeometryShaderManager::SetConstants();
- PixelShaderManager::SetConstants();
+ DrawCurrentBatch(base_index, num_indices, base_vertex);
+ INCSTAT(stats.thisFrame.numDrawCalls);
- if (PerfQueryBase::ShouldEmulate())
- g_perf_query->EnableQuery(bpmem.zcontrol.early_ztest ? PQG_ZCOMP_ZCOMPLOC : PQG_ZCOMP);
- g_vertex_manager->vFlush();
- if (PerfQueryBase::ShouldEmulate())
- g_perf_query->DisableQuery(bpmem.zcontrol.early_ztest ? PQG_ZCOMP_ZCOMPLOC : PQG_ZCOMP);
+ if (PerfQueryBase::ShouldEmulate())
+ g_perf_query->DisableQuery(bpmem.zcontrol.early_ztest ? PQG_ZCOMP_ZCOMPLOC : PQG_ZCOMP);
+ }
}
GFX_DEBUGGER_PAUSE_AT(NEXT_FLUSH, true);
@@ -413,7 +452,6 @@ void VertexManagerBase::Flush()
void VertexManagerBase::DoState(PointerWrap& p)
{
p.Do(m_zslope);
- g_vertex_manager->vDoState(p);
}
void VertexManagerBase::CalculateZSlope(NativeVertexFormat* format)
diff --git a/Source/Core/VideoCommon/VertexManagerBase.h b/Source/Core/VideoCommon/VertexManagerBase.h
index 88d9d9fbe0..cd3e4ed552 100644
--- a/Source/Core/VideoCommon/VertexManagerBase.h
+++ b/Source/Core/VideoCommon/VertexManagerBase.h
@@ -69,9 +69,29 @@ public:
m_pipeline_config_changed = true;
}
+ // Utility pipeline drawing (e.g. EFB copies, post-processing, UI).
+ virtual void UploadUtilityUniforms(const void* uniforms, u32 uniforms_size) = 0;
+ void UploadUtilityVertices(const void* vertices, u32 vertex_stride, u32 num_vertices,
+ const u16* indices, u32 num_indices, u32* out_base_vertex,
+ u32* out_base_index);
+
protected:
- virtual void vDoState(PointerWrap& p) {}
- virtual void ResetBuffer(u32 stride) = 0;
+ // Vertex buffers/index buffer creation.
+ virtual void CreateDeviceObjects() {}
+ virtual void DestroyDeviceObjects() {}
+
+ // Prepares the buffer for the next batch of vertices.
+ virtual void ResetBuffer(u32 vertex_stride, bool cull_all) = 0;
+
+ // Commits/uploads the current batch of vertices.
+ virtual void CommitBuffer(u32 num_vertices, u32 vertex_stride, u32 num_indices,
+ u32* out_base_vertex, u32* out_base_index) = 0;
+
+ // Uploads uniform buffers for GX draws.
+ virtual void UploadConstants() = 0;
+
+ // Issues the draw call for the current batch in the backend.
+ virtual void DrawCurrentBatch(u32 base_index, u32 num_indices, u32 base_vertex) = 0;
u8* m_cur_buffer_pointer = nullptr;
u8* m_base_buffer_pointer = nullptr;
@@ -98,10 +118,6 @@ private:
size_t m_flush_count_4_3 = 0;
size_t m_flush_count_anamorphic = 0;
- virtual void vFlush() = 0;
-
- virtual void CreateDeviceObjects() {}
- virtual void DestroyDeviceObjects() {}
void UpdatePipelineConfig();
void UpdatePipelineObject();
};