VideoBackends: Add AbstractShader and AbstractPipeline classes

This commit is contained in:
Stenzek
2017-09-08 19:42:56 +10:00
parent 31111ef143
commit fec6bb4d56
47 changed files with 1825 additions and 33 deletions

View File

@ -3,6 +3,8 @@ set(SRCS
FramebufferManager.cpp
main.cpp
NativeVertexFormat.cpp
OGLPipeline.cpp
OGLShader.cpp
OGLTexture.cpp
PerfQuery.cpp
PostProcessing.cpp

View File

@ -36,6 +36,8 @@
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<ItemGroup>
<ClCompile Include="OGLPipeline.cpp" />
<ClCompile Include="OGLShader.cpp" />
<ClCompile Include="OGLTexture.cpp" />
<ClCompile Include="BoundingBox.cpp" />
<ClCompile Include="FramebufferManager.cpp" />
@ -53,6 +55,8 @@
<ClCompile Include="VertexManager.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="OGLPipeline.h" />
<ClInclude Include="OGLShader.h" />
<ClInclude Include="OGLTexture.h" />
<ClInclude Include="BoundingBox.h" />
<ClInclude Include="FramebufferManager.h" />

View File

@ -56,6 +56,12 @@
<ClCompile Include="OGLTexture.cpp">
<Filter>Render</Filter>
</ClCompile>
<ClCompile Include="OGLShader.cpp">
<Filter>Render</Filter>
</ClCompile>
<ClCompile Include="OGLPipeline.cpp">
<Filter>Render</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="VertexManager.h">
@ -99,6 +105,12 @@
<ClInclude Include="OGLTexture.h">
<Filter>Render</Filter>
</ClInclude>
<ClInclude Include="OGLShader.h">
<Filter>Render</Filter>
</ClInclude>
<ClInclude Include="OGLPipeline.h">
<Filter>Render</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Text Include="CMakeLists.txt" />

View File

@ -0,0 +1,62 @@
// Copyright 2017 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#include "Common/Assert.h"
#include "VideoBackends/OGL/OGLPipeline.h"
#include "VideoBackends/OGL/OGLShader.h"
#include "VideoBackends/OGL/ProgramShaderCache.h"
#include "VideoBackends/OGL/Render.h"
#include "VideoBackends/OGL/VertexManager.h"
namespace OGL
{
static GLenum MapToGLPrimitive(PrimitiveType primitive_type)
{
switch (primitive_type)
{
case PrimitiveType::Points:
return GL_POINTS;
case PrimitiveType::Lines:
return GL_LINES;
case PrimitiveType::Triangles:
return GL_TRIANGLES;
case PrimitiveType::TriangleStrip:
return GL_TRIANGLE_STRIP;
default:
return 0;
}
}
OGLPipeline::OGLPipeline(const GLVertexFormat* vertex_format,
const RasterizationState& rasterization_state,
const DepthState& depth_state, const BlendingState& blending_state,
const PipelineProgram* program, GLuint gl_primitive)
: m_vertex_format(vertex_format), m_rasterization_state(rasterization_state),
m_depth_state(depth_state), m_blending_state(blending_state), m_program(program),
m_gl_primitive(gl_primitive)
{
}
OGLPipeline::~OGLPipeline()
{
// We don't want to destroy the shaders.
ProgramShaderCache::ReleasePipelineProgram(m_program);
}
std::unique_ptr<OGLPipeline> OGLPipeline::Create(const AbstractPipelineConfig& config)
{
const PipelineProgram* program =
ProgramShaderCache::GetPipelineProgram(static_cast<const OGLShader*>(config.vertex_shader),
static_cast<const OGLShader*>(config.geometry_shader),
static_cast<const OGLShader*>(config.pixel_shader));
if (!program)
return nullptr;
const GLVertexFormat* vertex_format = static_cast<const GLVertexFormat*>(config.vertex_format);
GLenum gl_primitive = MapToGLPrimitive(config.rasterization_state.primitive);
return std::make_unique<OGLPipeline>(vertex_format, config.rasterization_state,
config.depth_state, config.blending_state, program,
gl_primitive);
}
} // namespace OGL

View File

@ -0,0 +1,43 @@
// Copyright 2017 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#pragma once
#include <memory>
#include "Common/GL/GLUtil.h"
#include "VideoBackends/OGL/ProgramShaderCache.h"
#include "VideoCommon/AbstractPipeline.h"
#include "VideoCommon/RenderState.h"
namespace OGL
{
class OGLPipeline final : public AbstractPipeline
{
public:
explicit OGLPipeline(const GLVertexFormat* vertex_format,
const RasterizationState& rasterization_state, const DepthState& depth_state,
const BlendingState& blending_state, const PipelineProgram* program,
GLenum gl_primitive);
~OGLPipeline() override;
const GLVertexFormat* GetVertexFormat() const { return m_vertex_format; }
const RasterizationState& GetRasterizationState() const { return m_rasterization_state; }
const DepthState& GetDepthState() const { return m_depth_state; }
const BlendingState& GetBlendingState() const { return m_blending_state; }
const PipelineProgram* GetProgram() const { return m_program; }
bool HasVertexInput() const { return m_vertex_format != nullptr; }
GLenum GetGLPrimitive() const { return m_gl_primitive; }
static std::unique_ptr<OGLPipeline> Create(const AbstractPipelineConfig& config);
private:
const GLVertexFormat* m_vertex_format;
RasterizationState m_rasterization_state;
DepthState m_depth_state;
BlendingState m_blending_state;
const PipelineProgram* m_program;
GLenum m_gl_primitive;
};
} // namespace OGL

View File

@ -0,0 +1,77 @@
// Copyright 2017 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#include "VideoBackends/OGL/OGLShader.h"
#include "VideoBackends/OGL/ProgramShaderCache.h"
namespace OGL
{
static GLenum GetGLShaderTypeForStage(ShaderStage stage)
{
switch (stage)
{
case ShaderStage::Vertex:
return GL_VERTEX_SHADER;
case ShaderStage::Geometry:
return GL_GEOMETRY_SHADER;
case ShaderStage::Pixel:
return GL_FRAGMENT_SHADER;
case ShaderStage::Compute:
return GL_COMPUTE_SHADER;
default:
return 0;
}
}
OGLShader::OGLShader(ShaderStage stage, GLenum gl_type, GLuint shader_id)
: AbstractShader(stage), m_type(gl_type), m_id(shader_id)
{
}
OGLShader::OGLShader(GLuint compute_program_id)
: AbstractShader(ShaderStage::Compute), m_type(GL_COMPUTE_SHADER), m_id(compute_program_id)
{
}
OGLShader::~OGLShader()
{
if (m_stage != ShaderStage::Compute)
glDeleteShader(m_id);
else
glDeleteProgram(m_compute_program_id);
}
bool OGLShader::HasBinary() const
{
// NOTE: GL shaders do not have binaries, programs do.
return false;
}
AbstractShader::BinaryData OGLShader::GetBinary() const
{
return {};
}
std::unique_ptr<OGLShader> OGLShader::CreateFromSource(ShaderStage stage, const char* source,
size_t length)
{
if (stage != ShaderStage::Compute)
{
GLenum shader_type = GetGLShaderTypeForStage(stage);
GLuint shader_id =
ProgramShaderCache::CompileSingleShader(shader_type, std::string(source, length));
if (!shader_id)
return nullptr;
return std::make_unique<OGLShader>(stage, shader_type, shader_id);
}
// Compute shaders.
SHADER prog;
if (!ProgramShaderCache::CompileComputeShader(prog, std::string(source, length)))
return nullptr;
return std::make_unique<OGLShader>(prog.glprogid);
}
} // namespace OGL

View File

@ -0,0 +1,38 @@
// Copyright 2017 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#pragma once
#include <cstddef>
#include <memory>
#include "Common/CommonTypes.h"
#include "Common/GL/GLUtil.h"
#include "VideoCommon/AbstractShader.h"
namespace OGL
{
class OGLShader final : public AbstractShader
{
public:
explicit OGLShader(ShaderStage stage, GLenum gl_type, GLuint shader_id);
explicit OGLShader(GLuint compute_program_id);
~OGLShader() override;
GLenum GetGLShaderType() const { return m_type; }
GLuint GetGLShaderID() const { return m_id; }
GLuint GetGLComputeProgramID() const { return m_compute_program_id; }
bool HasBinary() const override;
BinaryData GetBinary() const override;
static std::unique_ptr<OGLShader> CreateFromSource(ShaderStage stage, const char* source,
size_t length);
private:
GLenum m_type;
GLuint m_id;
GLuint m_compute_program_id;
};
} // namespace OGL

View File

@ -9,6 +9,7 @@
#include <string>
#include "Common/Align.h"
#include "Common/Assert.h"
#include "Common/CommonTypes.h"
#include "Common/FileUtil.h"
#include "Common/GL/GLInterfaceBase.h"
@ -20,6 +21,7 @@
#include "Core/ConfigManager.h"
#include "Core/Host.h"
#include "VideoBackends/OGL/OGLShader.h"
#include "VideoBackends/OGL/Render.h"
#include "VideoBackends/OGL/StreamBuffer.h"
#include "VideoBackends/OGL/VertexManager.h"
@ -57,6 +59,7 @@ static LinearDiskCache<UBERSHADERUID, u8> s_uber_program_disk_cache;
static GLuint CurrentProgram = 0;
ProgramShaderCache::PCache ProgramShaderCache::pshaders;
ProgramShaderCache::UberPCache ProgramShaderCache::ubershaders;
ProgramShaderCache::PipelineProgramMap ProgramShaderCache::pipelineprograms;
ProgramShaderCache::PCacheEntry* ProgramShaderCache::last_entry;
ProgramShaderCache::PCacheEntry* ProgramShaderCache::last_uber_entry;
SHADERUID ProgramShaderCache::last_uid;
@ -188,6 +191,47 @@ void SHADER::DestroyShaders()
}
}
bool PipelineProgramKey::operator!=(const PipelineProgramKey& rhs) const
{
return !operator==(rhs);
}
bool PipelineProgramKey::operator==(const PipelineProgramKey& rhs) const
{
return std::tie(vertex_shader, geometry_shader, pixel_shader) ==
std::tie(rhs.vertex_shader, rhs.geometry_shader, rhs.pixel_shader);
}
bool PipelineProgramKey::operator<(const PipelineProgramKey& rhs) const
{
return std::tie(vertex_shader, geometry_shader, pixel_shader) <
std::tie(rhs.vertex_shader, rhs.geometry_shader, rhs.pixel_shader);
}
std::size_t PipelineProgramKeyHash::operator()(const PipelineProgramKey& key) const
{
// We would really want std::hash_combine for this..
std::hash<const void*> hasher;
return hasher(key.vertex_shader) + hasher(key.geometry_shader) + hasher(key.pixel_shader);
}
StreamBuffer* ProgramShaderCache::GetUniformBuffer()
{
return s_buffer.get();
}
u32 ProgramShaderCache::GetUniformBufferAlignment()
{
return s_ubo_align;
}
void ProgramShaderCache::InvalidateConstants()
{
VertexShaderManager::dirty = true;
GeometryShaderManager::dirty = true;
PixelShaderManager::dirty = true;
}
void ProgramShaderCache::UploadConstants()
{
if (PixelShaderManager::dirty || VertexShaderManager::dirty || GeometryShaderManager::dirty)
@ -697,6 +741,10 @@ void ProgramShaderCache::Shutdown()
s_attributeless_VBO = 0;
s_attributeless_VAO = 0;
s_last_VAO = 0;
// All pipeline programs should have been released.
_dbg_assert_(VIDEO, pipelineprograms.empty());
pipelineprograms.clear();
}
void ProgramShaderCache::CreateAttributelessVAO()
@ -732,6 +780,11 @@ void ProgramShaderCache::InvalidateVertexFormat()
s_last_VAO = 0;
}
void ProgramShaderCache::InvalidateLastProgram()
{
CurrentProgram = 0;
}
GLuint ProgramShaderCache::CreateProgramFromBinary(const u8* value, u32 value_size)
{
const u8* binary = value + sizeof(GLenum);
@ -860,6 +913,58 @@ void ProgramShaderCache::DestroyShaders()
ubershaders.clear();
}
const PipelineProgram* ProgramShaderCache::GetPipelineProgram(const OGLShader* vertex_shader,
const OGLShader* geometry_shader,
const OGLShader* pixel_shader)
{
PipelineProgramKey key = {vertex_shader, geometry_shader, pixel_shader};
auto iter = pipelineprograms.find(key);
if (iter != pipelineprograms.end())
{
iter->second->reference_count++;
return iter->second.get();
}
std::unique_ptr<PipelineProgram> prog = std::make_unique<PipelineProgram>();
prog->key = key;
// Attach shaders.
_assert_(vertex_shader && vertex_shader->GetStage() == ShaderStage::Vertex);
_assert_(pixel_shader && pixel_shader->GetStage() == ShaderStage::Pixel);
prog->shader.glprogid = glCreateProgram();
glAttachShader(prog->shader.glprogid, vertex_shader->GetGLShaderID());
glAttachShader(prog->shader.glprogid, pixel_shader->GetGLShaderID());
if (geometry_shader)
{
_assert_(geometry_shader->GetStage() == ShaderStage::Geometry);
glAttachShader(prog->shader.glprogid, geometry_shader->GetGLShaderID());
}
// Link program.
prog->shader.SetProgramBindings(false);
glLinkProgram(prog->shader.glprogid);
if (!ProgramShaderCache::CheckProgramLinkResult(prog->shader.glprogid, {}, {}, {}))
{
prog->shader.Destroy();
return nullptr;
}
auto ip = pipelineprograms.emplace(key, std::move(prog));
return ip.first->second.get();
}
void ProgramShaderCache::ReleasePipelineProgram(const PipelineProgram* prog)
{
auto iter = pipelineprograms.find(prog->key);
_assert_(iter != pipelineprograms.end() && prog == iter->second.get());
if (--iter->second->reference_count == 0)
{
iter->second->shader.Destroy();
pipelineprograms.erase(iter);
}
}
void ProgramShaderCache::CreateHeader()
{
GlslVersion v = g_ogl_config.eSupportedGLSLVersion;
@ -1368,5 +1473,4 @@ void ProgramShaderCache::DrawPrerenderArray(const SHADER& shader, PrimitiveType
glClientWaitSync(sync, GL_SYNC_FLUSH_COMMANDS_BIT, GL_TIMEOUT_IGNORED);
glDeleteSync(sync);
}
} // namespace OGL

View File

@ -4,8 +4,10 @@
#pragma once
#include <atomic>
#include <memory>
#include <tuple>
#include <unordered_map>
#include "Common/GL/GLUtil.h"
#include "Common/LinearDiskCache.h"
@ -21,7 +23,9 @@ class cInterfaceBase;
namespace OGL
{
class OGLShader;
class GLVertexFormat;
class StreamBuffer;
class SHADERUID
{
@ -81,6 +85,29 @@ struct SHADER
void DestroyShaders();
};
struct PipelineProgramKey
{
const OGLShader* vertex_shader;
const OGLShader* geometry_shader;
const OGLShader* pixel_shader;
bool operator==(const PipelineProgramKey& rhs) const;
bool operator!=(const PipelineProgramKey& rhs) const;
bool operator<(const PipelineProgramKey& rhs) const;
};
struct PipelineProgramKeyHash
{
std::size_t operator()(const PipelineProgramKey& key) const;
};
struct PipelineProgram
{
PipelineProgramKey key;
SHADER shader;
std::atomic_size_t reference_count{1};
};
class ProgramShaderCache
{
public:
@ -98,6 +125,7 @@ public:
static SHADER* SetUberShader(PrimitiveType primitive_type, const GLVertexFormat* vertex_format);
static void BindVertexFormat(const GLVertexFormat* vertex_format);
static void InvalidateVertexFormat();
static void InvalidateLastProgram();
static bool CompileShader(SHADER& shader, const std::string& vcode, const std::string& pcode,
const std::string& gcode = "");
@ -106,6 +134,9 @@ public:
static bool CheckShaderCompileResult(GLuint id, GLenum type, const std::string& code);
static bool CheckProgramLinkResult(GLuint id, const std::string& vcode, const std::string& pcode,
const std::string& gcode);
static StreamBuffer* GetUniformBuffer();
static u32 GetUniformBufferAlignment();
static void InvalidateConstants();
static void UploadConstants();
static void Init();
@ -115,6 +146,11 @@ public:
static void RetrieveAsyncShaders();
static void PrecompileUberShaders();
static const PipelineProgram* GetPipelineProgram(const OGLShader* vertex_shader,
const OGLShader* geometry_shader,
const OGLShader* pixel_shader);
static void ReleasePipelineProgram(const PipelineProgram* prog);
private:
template <typename UIDType>
class ProgramShaderCacheInserter : public LinearDiskCacheReader<UIDType, u8>
@ -189,6 +225,9 @@ private:
typedef std::map<SHADERUID, PCacheEntry> PCache;
typedef std::map<UBERSHADERUID, PCacheEntry> UberPCache;
typedef std::unordered_map<PipelineProgramKey, std::unique_ptr<PipelineProgram>,
PipelineProgramKeyHash>
PipelineProgramMap;
static void CreateAttributelessVAO();
static GLuint CreateProgramFromBinary(const u8* value, u32 value_size);
@ -202,6 +241,7 @@ private:
static PCache pshaders;
static UberPCache ubershaders;
static PipelineProgramMap pipelineprograms;
static PCacheEntry* last_entry;
static PCacheEntry* last_uber_entry;
static SHADERUID last_uid;

View File

@ -13,6 +13,7 @@
#include <tuple>
#include <vector>
#include "Common/Assert.h"
#include "Common/Atomic.h"
#include "Common/CommonTypes.h"
#include "Common/GL/GLInterfaceBase.h"
@ -27,11 +28,14 @@
#include "VideoBackends/OGL/BoundingBox.h"
#include "VideoBackends/OGL/FramebufferManager.h"
#include "VideoBackends/OGL/OGLPipeline.h"
#include "VideoBackends/OGL/OGLShader.h"
#include "VideoBackends/OGL/OGLTexture.h"
#include "VideoBackends/OGL/PostProcessing.h"
#include "VideoBackends/OGL/ProgramShaderCache.h"
#include "VideoBackends/OGL/RasterFont.h"
#include "VideoBackends/OGL/SamplerCache.h"
#include "VideoBackends/OGL/StreamBuffer.h"
#include "VideoBackends/OGL/TextureCache.h"
#include "VideoBackends/OGL/VertexManager.h"
@ -847,6 +851,23 @@ void Renderer::RenderText(const std::string& text, int left, int top, u32 color)
m_backbuffer_width, m_backbuffer_height, color);
}
std::unique_ptr<AbstractShader> Renderer::CreateShaderFromSource(ShaderStage stage,
const char* source, size_t length)
{
return OGLShader::CreateFromSource(stage, source, length);
}
std::unique_ptr<AbstractShader> Renderer::CreateShaderFromBinary(ShaderStage stage,
const void* data, size_t length)
{
return nullptr;
}
std::unique_ptr<AbstractPipeline> Renderer::CreatePipeline(const AbstractPipelineConfig& config)
{
return OGLPipeline::Create(config);
}
TargetRectangle Renderer::ConvertEFBRectangle(const EFBRectangle& rc)
{
TargetRectangle result;
@ -1217,7 +1238,7 @@ void Renderer::ReinterpretPixelData(unsigned int convtype)
}
}
void Renderer::SetBlendingState(const BlendingState& state)
void Renderer::ApplyBlendingState(const BlendingState& state)
{
bool useDualSource =
state.usedualsrc && g_ActiveConfig.backend_info.bSupportsDualSourceBlend &&
@ -1491,7 +1512,7 @@ void Renderer::RestoreAPIState()
BPFunctions::SetBlendMode();
}
void Renderer::SetRasterizationState(const RasterizationState& state)
void Renderer::ApplyRasterizationState(const RasterizationState& state)
{
// none, ccw, cw, ccw
if (state.cullmode != GenMode::CULL_NONE)
@ -1506,7 +1527,7 @@ void Renderer::SetRasterizationState(const RasterizationState& state)
}
}
void Renderer::SetDepthState(const DepthState& state)
void Renderer::ApplyDepthState(const DepthState& state)
{
const GLenum glCmpFuncs[8] = {GL_NEVER, GL_LESS, GL_EQUAL, GL_LEQUAL,
GL_GREATER, GL_NOTEQUAL, GL_GEQUAL, GL_ALWAYS};
@ -1527,6 +1548,33 @@ void Renderer::SetDepthState(const DepthState& state)
}
}
void Renderer::SetRasterizationState(const RasterizationState& state)
{
ApplyRasterizationState(state);
}
void Renderer::SetDepthState(const DepthState& state)
{
ApplyDepthState(state);
}
void Renderer::SetBlendingState(const BlendingState& state)
{
ApplyBlendingState(state);
}
void Renderer::SetPipeline(const AbstractPipeline* pipeline)
{
// Not all shader changes currently go through SetPipeline, so we can't
// test if the pipeline hasn't changed and skip these applications. Yet.
m_graphics_pipeline = static_cast<const OGLPipeline*>(pipeline);
ApplyRasterizationState(m_graphics_pipeline->GetRasterizationState());
ApplyDepthState(m_graphics_pipeline->GetDepthState());
ApplyBlendingState(m_graphics_pipeline->GetBlendingState());
ProgramShaderCache::BindVertexFormat(m_graphics_pipeline->GetVertexFormat());
m_graphics_pipeline->GetProgram()->shader.Bind();
}
void Renderer::SetTexture(u32 index, const AbstractTexture* texture)
{
if (m_bound_textures[index] == texture)
@ -1559,4 +1607,52 @@ void Renderer::SetInterlacingMode()
{
// TODO
}
void Renderer::DrawUtilityPipeline(const void* uniforms, u32 uniforms_size, const void* vertices,
u32 vertex_stride, u32 num_vertices)
{
// Copy in uniforms.
if (uniforms_size > 0)
UploadUtilityUniforms(uniforms, uniforms_size);
// Draw from base index if there is vertex data.
if (vertices)
{
StreamBuffer* vbuf = static_cast<VertexManager*>(g_vertex_manager.get())->GetVertexBuffer();
auto buf = vbuf->Map(vertex_stride * num_vertices, vertex_stride);
std::memcpy(buf.first, vertices, vertex_stride * num_vertices);
vbuf->Unmap(vertex_stride * num_vertices);
glDrawArrays(m_graphics_pipeline->GetGLPrimitive(), buf.second / vertex_stride, num_vertices);
}
else
{
glDrawArrays(m_graphics_pipeline->GetGLPrimitive(), 0, num_vertices);
}
}
void Renderer::UploadUtilityUniforms(const void* uniforms, u32 uniforms_size)
{
_dbg_assert_(VIDEO, uniforms_size > 0);
auto buf = ProgramShaderCache::GetUniformBuffer()->Map(
uniforms_size, ProgramShaderCache::GetUniformBufferAlignment());
std::memcpy(buf.first, uniforms, uniforms_size);
ProgramShaderCache::GetUniformBuffer()->Unmap(uniforms_size);
glBindBufferRange(GL_UNIFORM_BUFFER, 1, ProgramShaderCache::GetUniformBuffer()->m_buffer,
buf.second, uniforms_size);
// This is rather horrible, but because of how the UBOs are bound, this forces it to rebind.
ProgramShaderCache::InvalidateConstants();
}
void Renderer::DispatchComputeShader(const AbstractShader* shader, const void* uniforms,
u32 uniforms_size, u32 groups_x, u32 groups_y, u32 groups_z)
{
glUseProgram(static_cast<const OGLShader*>(shader)->GetGLComputeProgramID());
if (uniforms_size > 0)
UploadUtilityUniforms(uniforms, uniforms_size);
glDispatchCompute(groups_x, groups_y, groups_z);
ProgramShaderCache::InvalidateLastProgram();
}
}

View File

@ -14,6 +14,7 @@ struct XFBSourceBase;
namespace OGL
{
class OGLPipeline;
void ClearEFBCache();
enum GlslVersion
@ -89,7 +90,13 @@ public:
std::unique_ptr<AbstractTexture> CreateTexture(const TextureConfig& config) override;
std::unique_ptr<AbstractStagingTexture>
CreateStagingTexture(StagingTextureType type, const TextureConfig& config) override;
std::unique_ptr<AbstractShader> CreateShaderFromSource(ShaderStage stage, const char* source,
size_t length) override;
std::unique_ptr<AbstractShader> CreateShaderFromBinary(ShaderStage stage, const void* data,
size_t length) override;
std::unique_ptr<AbstractPipeline> CreatePipeline(const AbstractPipelineConfig& config) override;
void SetPipeline(const AbstractPipeline* pipeline) override;
void SetBlendingState(const BlendingState& state) override;
void SetScissorRect(const MathUtil::Rectangle<int>& rc) override;
void SetRasterizationState(const RasterizationState& state) override;
@ -121,6 +128,12 @@ public:
void ReinterpretPixelData(unsigned int convtype) override;
void DrawUtilityPipeline(const void* uniforms, u32 uniforms_size, const void* vertices,
u32 vertex_stride, u32 num_vertices) override;
void DispatchComputeShader(const AbstractShader* shader, const void* uniforms, u32 uniforms_size,
u32 groups_x, u32 groups_y, u32 groups_z) override;
private:
void UpdateEFBCache(EFBAccessType type, u32 cacheRectIdx, const EFBRectangle& efbPixelRc,
const TargetRectangle& targetPixelRc, const void* data);
@ -134,6 +147,12 @@ private:
void CheckForSurfaceChange();
void CheckForSurfaceResize();
void ApplyBlendingState(const BlendingState& state);
void ApplyRasterizationState(const RasterizationState& state);
void ApplyDepthState(const DepthState& state);
void UploadUtilityUniforms(const void* uniforms, u32 uniforms_size);
std::array<const AbstractTexture*, 8> m_bound_textures{};
const OGLPipeline* m_graphics_pipeline = nullptr;
};
}

View File

@ -61,6 +61,16 @@ void VertexManager::DestroyDeviceObjects()
s_indexBuffer.reset();
}
StreamBuffer* VertexManager::GetVertexBuffer() const
{
return s_vertexBuffer.get();
}
OGL::StreamBuffer* VertexManager::GetIndexBuffer() const
{
return s_indexBuffer.get();
}
GLuint VertexManager::GetVertexBufferHandle() const
{
return m_vertex_buffers;

View File

@ -14,6 +14,7 @@
namespace OGL
{
class StreamBuffer;
class GLVertexFormat : public NativeVertexFormat
{
public:
@ -37,6 +38,8 @@ public:
void CreateDeviceObjects() override;
void DestroyDeviceObjects() override;
StreamBuffer* GetVertexBuffer() const;
StreamBuffer* GetIndexBuffer() const;
GLuint GetVertexBufferHandle() const;
GLuint GetIndexBufferHandle() const;