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

@ -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();
}
}