mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-23 22:29:39 -06:00
Merge pull request #6042 from stenzek/videocommon-pipelines
VideoCommon pipelines ("Abstract Pipeline")
This commit is contained in:
@ -3,6 +3,8 @@ set(SRCS
|
||||
FramebufferManager.cpp
|
||||
main.cpp
|
||||
NativeVertexFormat.cpp
|
||||
OGLPipeline.cpp
|
||||
OGLShader.cpp
|
||||
OGLTexture.cpp
|
||||
PerfQuery.cpp
|
||||
PostProcessing.cpp
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "VideoBackends/OGL/Render.h"
|
||||
#include "VideoBackends/OGL/SamplerCache.h"
|
||||
#include "VideoBackends/OGL/TextureConverter.h"
|
||||
#include "VideoBackends/OGL/VertexManager.h"
|
||||
|
||||
#include "VideoCommon/OnScreenDisplay.h"
|
||||
#include "VideoCommon/VertexShaderGen.h"
|
||||
@ -395,6 +396,8 @@ FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int ms
|
||||
glEnableVertexAttribArray(SHADER_COLOR1_ATTRIB);
|
||||
glVertexAttribIPointer(SHADER_COLOR1_ATTRIB, 1, GL_INT, sizeof(EfbPokeData),
|
||||
(void*)offsetof(EfbPokeData, data));
|
||||
glBindBuffer(GL_ARRAY_BUFFER,
|
||||
static_cast<VertexManager*>(g_vertex_manager.get())->GetVertexBufferHandle());
|
||||
|
||||
if (GLInterface->GetMode() == GLInterfaceMode::MODE_OPENGL)
|
||||
glEnable(GL_PROGRAM_POINT_SIZE);
|
||||
@ -563,8 +566,6 @@ void FramebufferManager::ReinterpretPixelData(unsigned int convtype)
|
||||
{
|
||||
g_renderer->ResetAPIState();
|
||||
|
||||
OpenGL_BindAttributelessVAO();
|
||||
|
||||
GLuint src_texture = 0;
|
||||
|
||||
// We aren't allowed to render and sample the same texture in one draw call,
|
||||
@ -582,6 +583,7 @@ void FramebufferManager::ReinterpretPixelData(unsigned int convtype)
|
||||
g_sampler_cache->BindNearestSampler(9);
|
||||
|
||||
m_pixel_format_shaders[convtype ? 1 : 0].Bind();
|
||||
ProgramShaderCache::BindVertexFormat(nullptr);
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
glBindTexture(m_textureType, 0);
|
||||
|
||||
@ -607,6 +609,8 @@ void FramebufferManager::PokeEFB(EFBAccessType type, const EfbPokeData* points,
|
||||
glViewport(0, 0, m_targetWidth, m_targetHeight);
|
||||
glDrawArrays(GL_POINTS, 0, (GLsizei)num_points);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER,
|
||||
static_cast<VertexManager*>(g_vertex_manager.get())->GetVertexBufferHandle());
|
||||
g_renderer->RestoreAPIState();
|
||||
|
||||
// TODO: Could just update the EFB cache with the new value
|
||||
|
@ -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" />
|
||||
|
@ -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" />
|
||||
|
62
Source/Core/VideoBackends/OGL/OGLPipeline.cpp
Normal file
62
Source/Core/VideoBackends/OGL/OGLPipeline.cpp
Normal 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
|
43
Source/Core/VideoBackends/OGL/OGLPipeline.h
Normal file
43
Source/Core/VideoBackends/OGL/OGLPipeline.h
Normal 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
|
77
Source/Core/VideoBackends/OGL/OGLShader.cpp
Normal file
77
Source/Core/VideoBackends/OGL/OGLShader.cpp
Normal 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
|
38
Source/Core/VideoBackends/OGL/OGLShader.h
Normal file
38
Source/Core/VideoBackends/OGL/OGLShader.h
Normal 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
|
@ -5,7 +5,6 @@
|
||||
#include "VideoBackends/OGL/PostProcessing.h"
|
||||
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Common/GL/GLUtil.h"
|
||||
#include "Common/Logging/Log.h"
|
||||
#include "Common/StringUtil.h"
|
||||
|
||||
@ -47,7 +46,7 @@ void OpenGLPostProcessing::BlitFromTexture(TargetRectangle src, TargetRectangle
|
||||
|
||||
glViewport(dst.left, dst.bottom, dst.GetWidth(), dst.GetHeight());
|
||||
|
||||
OpenGL_BindAttributelessVAO();
|
||||
ProgramShaderCache::BindVertexFormat(nullptr);
|
||||
|
||||
m_shader.Bind();
|
||||
|
||||
|
@ -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"
|
||||
@ -40,13 +42,14 @@
|
||||
namespace OGL
|
||||
{
|
||||
static constexpr u32 UBO_LENGTH = 32 * 1024 * 1024;
|
||||
static constexpr u32 INVALID_VAO = std::numeric_limits<u32>::max();
|
||||
|
||||
std::unique_ptr<ProgramShaderCache::SharedContextAsyncShaderCompiler>
|
||||
ProgramShaderCache::s_async_compiler;
|
||||
u32 ProgramShaderCache::s_ubo_buffer_size;
|
||||
s32 ProgramShaderCache::s_ubo_align;
|
||||
u32 ProgramShaderCache::s_last_VAO = INVALID_VAO;
|
||||
GLuint ProgramShaderCache::s_attributeless_VBO = 0;
|
||||
GLuint ProgramShaderCache::s_attributeless_VAO = 0;
|
||||
GLuint ProgramShaderCache::s_last_VAO = 0;
|
||||
|
||||
static std::unique_ptr<StreamBuffer> s_buffer;
|
||||
static int num_failures = 0;
|
||||
@ -56,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;
|
||||
@ -187,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)
|
||||
@ -484,8 +529,7 @@ bool ProgramShaderCache::CheckShaderCompileResult(GLuint id, GLenum type, const
|
||||
glGetShaderiv(id, GL_COMPILE_STATUS, &compileStatus);
|
||||
GLsizei length = 0;
|
||||
glGetShaderiv(id, GL_INFO_LOG_LENGTH, &length);
|
||||
|
||||
if (compileStatus != GL_TRUE || (length > 1 && DEBUG_GLSL))
|
||||
if (compileStatus != GL_TRUE || length > 1)
|
||||
{
|
||||
std::string info_log;
|
||||
info_log.resize(length);
|
||||
@ -508,7 +552,10 @@ bool ProgramShaderCache::CheckShaderCompileResult(GLuint id, GLenum type, const
|
||||
break;
|
||||
}
|
||||
|
||||
ERROR_LOG(VIDEO, "%s Shader info log:\n%s", prefix, info_log.c_str());
|
||||
if (compileStatus != GL_TRUE)
|
||||
ERROR_LOG(VIDEO, "%s failed compilation:\n%s", prefix, info_log.c_str());
|
||||
else
|
||||
WARN_LOG(VIDEO, "%s compiled with warnings:\n%s", prefix, info_log.c_str());
|
||||
|
||||
std::string filename = StringFromFormat(
|
||||
"%sbad_%s_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), prefix, num_failures++);
|
||||
@ -542,12 +589,16 @@ bool ProgramShaderCache::CheckProgramLinkResult(GLuint id, const std::string& vc
|
||||
glGetProgramiv(id, GL_LINK_STATUS, &linkStatus);
|
||||
GLsizei length = 0;
|
||||
glGetProgramiv(id, GL_INFO_LOG_LENGTH, &length);
|
||||
if (linkStatus != GL_TRUE || (length > 1 && DEBUG_GLSL))
|
||||
if (linkStatus != GL_TRUE || length > 1)
|
||||
{
|
||||
std::string info_log;
|
||||
info_log.resize(length);
|
||||
glGetProgramInfoLog(id, length, &length, &info_log[0]);
|
||||
ERROR_LOG(VIDEO, "Program info log:\n%s", info_log.c_str());
|
||||
|
||||
if (linkStatus != GL_TRUE)
|
||||
ERROR_LOG(VIDEO, "Program failed linking:\n%s", info_log.c_str());
|
||||
else
|
||||
WARN_LOG(VIDEO, "Program linked with warnings:\n%s", info_log.c_str());
|
||||
|
||||
std::string filename =
|
||||
StringFromFormat("%sbad_p_%d.txt", File::GetUserPath(D_DUMP_IDX).c_str(), num_failures++);
|
||||
@ -608,6 +659,7 @@ void ProgramShaderCache::Init()
|
||||
LoadProgramBinaries();
|
||||
|
||||
CreateHeader();
|
||||
CreateAttributelessVAO();
|
||||
|
||||
CurrentProgram = 0;
|
||||
last_entry = nullptr;
|
||||
@ -657,7 +709,6 @@ void ProgramShaderCache::Reload()
|
||||
if (g_ActiveConfig.CanPrecompileUberShaders())
|
||||
PrecompileUberShaders();
|
||||
|
||||
InvalidateVertexFormat();
|
||||
CurrentProgram = 0;
|
||||
last_entry = nullptr;
|
||||
last_uber_entry = nullptr;
|
||||
@ -681,14 +732,42 @@ void ProgramShaderCache::Shutdown()
|
||||
s_program_disk_cache.Close();
|
||||
s_uber_program_disk_cache.Close();
|
||||
|
||||
InvalidateVertexFormat();
|
||||
DestroyShaders();
|
||||
s_buffer.reset();
|
||||
|
||||
glBindVertexArray(0);
|
||||
glDeleteBuffers(1, &s_attributeless_VBO);
|
||||
glDeleteVertexArrays(1, &s_attributeless_VAO);
|
||||
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()
|
||||
{
|
||||
glGenVertexArrays(1, &s_attributeless_VAO);
|
||||
|
||||
// In a compatibility context, we require a valid, bound array buffer.
|
||||
glGenBuffers(1, &s_attributeless_VBO);
|
||||
|
||||
// Initialize the buffer with nothing. 16 floats is an arbitrary size that may work around driver
|
||||
// issues.
|
||||
glBindBuffer(GL_ARRAY_BUFFER, s_attributeless_VBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 16, nullptr, GL_STATIC_DRAW);
|
||||
|
||||
// We must also define vertex attribute 0.
|
||||
glBindVertexArray(s_attributeless_VAO);
|
||||
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
|
||||
glEnableVertexAttribArray(0);
|
||||
}
|
||||
|
||||
void ProgramShaderCache::BindVertexFormat(const GLVertexFormat* vertex_format)
|
||||
{
|
||||
u32 new_VAO = vertex_format ? vertex_format->VAO : 0;
|
||||
u32 new_VAO = vertex_format ? vertex_format->VAO : s_attributeless_VAO;
|
||||
if (s_last_VAO == new_VAO)
|
||||
return;
|
||||
|
||||
@ -698,15 +777,12 @@ void ProgramShaderCache::BindVertexFormat(const GLVertexFormat* vertex_format)
|
||||
|
||||
void ProgramShaderCache::InvalidateVertexFormat()
|
||||
{
|
||||
s_last_VAO = INVALID_VAO;
|
||||
s_last_VAO = 0;
|
||||
}
|
||||
|
||||
void ProgramShaderCache::BindLastVertexFormat()
|
||||
void ProgramShaderCache::InvalidateLastProgram()
|
||||
{
|
||||
if (s_last_VAO != INVALID_VAO)
|
||||
glBindVertexArray(s_last_VAO);
|
||||
else
|
||||
glBindVertexArray(0);
|
||||
CurrentProgram = 0;
|
||||
}
|
||||
|
||||
GLuint ProgramShaderCache::CreateProgramFromBinary(const u8* value, u32 value_size)
|
||||
@ -837,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;
|
||||
@ -1345,5 +1473,4 @@ void ProgramShaderCache::DrawPrerenderArray(const SHADER& shader, PrimitiveType
|
||||
glClientWaitSync(sync, GL_SYNC_FLUSH_COMMANDS_BIT, GL_TIMEOUT_IGNORED);
|
||||
glDeleteSync(sync);
|
||||
}
|
||||
|
||||
} // namespace OGL
|
||||
|
@ -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,7 +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 BindLastVertexFormat();
|
||||
static void InvalidateLastProgram();
|
||||
|
||||
static bool CompileShader(SHADER& shader, const std::string& vcode, const std::string& pcode,
|
||||
const std::string& gcode = "");
|
||||
@ -107,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();
|
||||
@ -116,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>
|
||||
@ -190,7 +225,11 @@ 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);
|
||||
static bool CreateCacheEntryFromBinary(PCacheEntry* entry, const u8* value, u32 value_size);
|
||||
static void LoadProgramBinaries();
|
||||
@ -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;
|
||||
@ -210,7 +250,10 @@ private:
|
||||
static std::unique_ptr<SharedContextAsyncShaderCompiler> s_async_compiler;
|
||||
static u32 s_ubo_buffer_size;
|
||||
static s32 s_ubo_align;
|
||||
static u32 s_last_VAO;
|
||||
|
||||
static GLuint s_attributeless_VBO;
|
||||
static GLuint s_attributeless_VAO;
|
||||
static GLuint s_last_VAO;
|
||||
};
|
||||
|
||||
} // namespace OGL
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
#include "VideoBackends/OGL/ProgramShaderCache.h"
|
||||
#include "VideoBackends/OGL/RasterFont.h"
|
||||
#include "VideoBackends/OGL/VertexManager.h"
|
||||
|
||||
// globals
|
||||
|
||||
@ -181,6 +182,9 @@ RasterFont::RasterFont()
|
||||
glEnableVertexAttribArray(SHADER_TEXTURE0_ATTRIB);
|
||||
glVertexAttribPointer(SHADER_TEXTURE0_ATTRIB, 2, GL_FLOAT, 0, sizeof(GLfloat) * 4,
|
||||
(GLfloat*)nullptr + 2);
|
||||
glBindBuffer(GL_ARRAY_BUFFER,
|
||||
static_cast<VertexManager*>(g_vertex_manager.get())->GetVertexBufferHandle());
|
||||
ProgramShaderCache::InvalidateVertexFormat();
|
||||
}
|
||||
|
||||
RasterFont::~RasterFont()
|
||||
@ -278,5 +282,9 @@ void RasterFont::printMultilineText(const std::string& text, double start_x, dou
|
||||
GLfloat((color >> 8) & 0xff) / 255.f, GLfloat((color >> 0) & 0xff) / 255.f,
|
||||
GLfloat((color >> 24) & 0xff) / 255.f);
|
||||
glDrawArrays(GL_TRIANGLES, 0, usage / 4);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER,
|
||||
static_cast<VertexManager*>(g_vertex_manager.get())->GetVertexBufferHandle());
|
||||
ProgramShaderCache::InvalidateVertexFormat();
|
||||
}
|
||||
}
|
||||
|
@ -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"
|
||||
|
||||
@ -816,8 +820,6 @@ void Renderer::Shutdown()
|
||||
|
||||
s_raster_font.reset();
|
||||
m_post_processor.reset();
|
||||
|
||||
OpenGL_DeleteAttributelessVAO();
|
||||
}
|
||||
|
||||
void Renderer::Init()
|
||||
@ -828,8 +830,6 @@ void Renderer::Init()
|
||||
|
||||
m_post_processor = std::make_unique<OpenGLPostProcessing>();
|
||||
s_raster_font = std::make_unique<RasterFont>();
|
||||
|
||||
OpenGL_CreateAttributelessVAO();
|
||||
}
|
||||
|
||||
std::unique_ptr<AbstractTexture> Renderer::CreateTexture(const TextureConfig& config)
|
||||
@ -851,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;
|
||||
@ -1221,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 &&
|
||||
@ -1494,13 +1511,9 @@ void Renderer::RestoreAPIState()
|
||||
BPFunctions::SetViewport();
|
||||
BPFunctions::SetDepthMode();
|
||||
BPFunctions::SetBlendMode();
|
||||
|
||||
ProgramShaderCache::BindLastVertexFormat();
|
||||
const VertexManager* const vm = static_cast<VertexManager*>(g_vertex_manager.get());
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vm->GetVertexBufferHandle());
|
||||
}
|
||||
|
||||
void Renderer::SetRasterizationState(const RasterizationState& state)
|
||||
void Renderer::ApplyRasterizationState(const RasterizationState& state)
|
||||
{
|
||||
// none, ccw, cw, ccw
|
||||
if (state.cullmode != GenMode::CULL_NONE)
|
||||
@ -1515,7 +1528,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};
|
||||
@ -1536,6 +1549,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)
|
||||
@ -1568,4 +1608,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();
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
}
|
||||
|
@ -320,7 +320,7 @@ void TextureCache::ConvertTexture(TCacheEntry* destination, TCacheEntry* source,
|
||||
glBindTexture(GL_TEXTURE_BUFFER, m_palette_resolv_texture);
|
||||
g_sampler_cache->BindNearestSampler(10);
|
||||
|
||||
OpenGL_BindAttributelessVAO();
|
||||
ProgramShaderCache::BindVertexFormat(nullptr);
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
|
||||
FramebufferManager::SetFramebuffer(0);
|
||||
@ -496,8 +496,6 @@ void TextureCache::CopyEFBToCacheEntry(TCacheEntry* entry, bool is_depth_copy,
|
||||
|
||||
FramebufferManager::SetFramebuffer(destination_texture->GetFramebuffer());
|
||||
|
||||
OpenGL_BindAttributelessVAO();
|
||||
|
||||
glActiveTexture(GL_TEXTURE9);
|
||||
glBindTexture(GL_TEXTURE_2D_ARRAY, read_texture);
|
||||
if (scale_by_half)
|
||||
@ -539,6 +537,7 @@ void TextureCache::CopyEFBToCacheEntry(TCacheEntry* entry, bool is_depth_copy,
|
||||
glUniform4f(shader.position_uniform, static_cast<float>(R.left), static_cast<float>(R.top),
|
||||
static_cast<float>(R.right), static_cast<float>(R.bottom));
|
||||
|
||||
ProgramShaderCache::BindVertexFormat(nullptr);
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
|
||||
FramebufferManager::SetFramebuffer(0);
|
||||
|
@ -111,8 +111,6 @@ static void EncodeToRamUsingShader(GLuint srcTexture, u8* destAddr, u32 dst_line
|
||||
FramebufferManager::SetFramebuffer(
|
||||
static_cast<OGLTexture*>(s_encoding_render_texture.get())->GetFramebuffer());
|
||||
|
||||
OpenGL_BindAttributelessVAO();
|
||||
|
||||
// set source texture
|
||||
glActiveTexture(GL_TEXTURE9);
|
||||
glBindTexture(GL_TEXTURE_2D_ARRAY, srcTexture);
|
||||
@ -128,6 +126,7 @@ static void EncodeToRamUsingShader(GLuint srcTexture, u8* destAddr, u32 dst_line
|
||||
|
||||
glViewport(0, 0, (GLsizei)(dst_line_size / 4), (GLsizei)dstHeight);
|
||||
|
||||
ProgramShaderCache::BindVertexFormat(nullptr);
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
|
||||
MathUtil::Rectangle<int> copy_rect(0, 0, dst_line_size / 4, dstHeight);
|
||||
|
@ -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;
|
||||
@ -95,6 +105,11 @@ void VertexManager::ResetBuffer(u32 stride)
|
||||
}
|
||||
else
|
||||
{
|
||||
// The index buffer is part of the VAO state, therefore we need to bind it first.
|
||||
const GLVertexFormat* vertex_format =
|
||||
static_cast<GLVertexFormat*>(VertexLoaderManager::GetCurrentVertexFormat());
|
||||
ProgramShaderCache::BindVertexFormat(vertex_format);
|
||||
|
||||
auto buffer = s_vertexBuffer->Map(MAXVBUFFERSIZE, stride);
|
||||
m_cur_buffer_pointer = m_base_buffer_pointer = buffer.first;
|
||||
m_end_buffer_pointer = buffer.first + MAXVBUFFERSIZE;
|
||||
|
@ -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;
|
||||
|
||||
|
Reference in New Issue
Block a user