OGL: implement bounding box support with ssbo

This implemention tries to be as accurate as the old SW implemention, but it will remove the dependcy of our vertexloader on videosw.
This commit is contained in:
degasus
2014-11-13 23:26:49 +01:00
parent dced84d440
commit c211450b99
24 changed files with 231 additions and 7 deletions

View File

@ -0,0 +1,54 @@
// Copyright 2014 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#include "VideoBackends/OGL/BoundingBox.h"
#include "VideoBackends/OGL/GLUtil.h"
#include "VideoCommon/VideoConfig.h"
static GLuint s_bbox_buffer_id;
namespace OGL
{
void BoundingBox::Init()
{
if (g_ActiveConfig.backend_info.bSupportsBBox)
{
int initial_values[4] = {0,0,0,0};
glGenBuffers(1, &s_bbox_buffer_id);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, s_bbox_buffer_id);
glBufferData(GL_SHADER_STORAGE_BUFFER, 4 * sizeof(s32), initial_values, GL_DYNAMIC_DRAW);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, s_bbox_buffer_id);
}
}
void BoundingBox::Shutdown()
{
if (g_ActiveConfig.backend_info.bSupportsBBox)
glDeleteBuffers(1, &s_bbox_buffer_id);
}
void BoundingBox::Set(int index, int value)
{
glBindBuffer(GL_SHADER_STORAGE_BUFFER, s_bbox_buffer_id);
glBufferSubData(GL_SHADER_STORAGE_BUFFER, index * sizeof(int), sizeof(int), &value);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
}
int BoundingBox::Get(int index)
{
int data = 0;
glBindBuffer(GL_SHADER_STORAGE_BUFFER, s_bbox_buffer_id);
void* ptr = glMapBufferRange(GL_SHADER_STORAGE_BUFFER, index * sizeof(int), sizeof(int), GL_MAP_READ_BIT);
if (ptr)
{
data = *(int*)ptr;
glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
}
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
return data;
}
};

View File

@ -0,0 +1,20 @@
// Copyright 2014 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#pragma once
namespace OGL
{
class BoundingBox
{
public:
static void Init();
static void Shutdown();
static void Set(int index, int value);
static int Get(int index);
};
};

View File

@ -1,4 +1,5 @@
set(SRCS GLExtensions/GLExtensions.cpp
BoundingBox.cpp
FramebufferManager.cpp
GLUtil.cpp
main.cpp

View File

@ -35,6 +35,7 @@
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<ItemGroup>
<ClCompile Include="BoundingBox.cpp" />
<ClCompile Include="FramebufferManager.cpp" />
<ClCompile Include="GLExtensions\GLExtensions.cpp" />
<ClCompile Include="GLInterface\GLInterface.cpp" />
@ -54,6 +55,7 @@
<ClCompile Include="VertexManager.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="BoundingBox.h" />
<ClInclude Include="FramebufferManager.h" />
<ClInclude Include="GLExtensions\ARB_blend_func_extended.h" />
<ClInclude Include="GLExtensions\ARB_buffer_storage.h" />
@ -111,4 +113,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
</Project>

View File

@ -36,6 +36,9 @@
<ClCompile Include="RasterFont.cpp">
<Filter>Logging</Filter>
</ClCompile>
<ClCompile Include="BoundingBox.cpp">
<Filter>Render</Filter>
</ClCompile>
<ClCompile Include="FramebufferManager.cpp">
<Filter>Render</Filter>
</ClCompile>
@ -82,6 +85,9 @@
<ClInclude Include="RasterFont.h">
<Filter>Logging</Filter>
</ClInclude>
<ClInclude Include="BoundingBox.h">
<Filter>Render</Filter>
</ClInclude>
<ClInclude Include="FramebufferManager.h">
<Filter>Render</Filter>
</ClInclude>

View File

@ -485,6 +485,7 @@ void ProgramShaderCache::CreateHeader()
"%s\n" // msaa
"%s\n" // sample shading
"%s\n" // Sampler binding
"%s\n" // storage buffer
// Precision defines for GLSL ES
"%s\n"
@ -516,6 +517,7 @@ void ProgramShaderCache::CreateHeader()
, (g_ogl_config.bSupportsMSAA && v < GLSL_150) ? "#extension GL_ARB_texture_multisample : enable" : ""
, (g_ogl_config.bSupportSampleShading) ? "#extension GL_ARB_sample_shading : enable" : ""
, g_ActiveConfig.backend_info.bSupportsBindingLayout ? "#define SAMPLER_BINDING(x) layout(binding = x)" : "#define SAMPLER_BINDING(x)"
, g_ActiveConfig.backend_info.bSupportsBBox ? "#extension GL_ARB_shader_storage_buffer_object : enable" : ""
, v>=GLSLES_300 ? "precision highp float;" : ""
, v>=GLSLES_300 ? "precision highp int;" : ""

View File

@ -20,6 +20,7 @@
#include "Core/Core.h"
#include "Core/Movie.h"
#include "VideoBackends/OGL/BoundingBox.h"
#include "VideoBackends/OGL/FramebufferManager.h"
#include "VideoBackends/OGL/GLInterfaceBase.h"
#include "VideoBackends/OGL/GLUtil.h"
@ -465,6 +466,7 @@ Renderer::Renderer()
g_Config.backend_info.bSupportsPrimitiveRestart = !DriverDetails::HasBug(DriverDetails::BUG_PRIMITIVERESTART) &&
((GLExtensions::Version() >= 310) || GLExtensions::Supports("GL_NV_primitive_restart"));
g_Config.backend_info.bSupportsEarlyZ = GLExtensions::Supports("GL_ARB_shader_image_load_store");
g_Config.backend_info.bSupportsBBox = GLExtensions::Supports("GL_ARB_shader_storage_buffer_object");
// Desktop OpenGL supports the binding layout if it supports 420pack
// OpenGL ES 3.1 supports it implicitly without an extension
@ -1161,6 +1163,52 @@ u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data)
return 0;
}
u16 Renderer::BBoxRead(int index)
{
int swapped_index = index;
if (index >= 2)
swapped_index ^= 1; // swap 2 and 3 for top/bottom
// Here we get the min/max value of the truncated position of the upscaled and swapped framebuffer.
// So we have to correct them to the unscaled EFB sizes.
int value = BoundingBox::Get(swapped_index);
if (index < 2)
{
// left/right
value = value * EFB_WIDTH / s_target_width;
}
else
{
// up/down -- we have to swap up and down
value = value * EFB_HEIGHT / s_target_height;
value = EFB_HEIGHT - value - 1;
}
if (index & 1)
value++; // fix max values to describe the outer border
return value;
}
void Renderer::BBoxWrite(int index, u16 _value)
{
int value = _value; // u16 isn't enough to multiply by the efb width
if (index & 1)
value--;
if (index < 2)
{
value = value * s_target_width / EFB_WIDTH;
}
else
{
index ^= 1; // swap 2 and 3 for top/bottom
value = EFB_HEIGHT - value - 1;
value = value * s_target_height / EFB_HEIGHT;
}
BoundingBox::Set(index, value);
}
void Renderer::SetViewport()
{
// reversed gxsetviewport(xorig, yorig, width, height, nearz, farz)

View File

@ -71,6 +71,9 @@ public:
u32 AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data) override;
u16 BBoxRead(int index) override;
void BBoxWrite(int index, u16 value) override;
void ResetAPIState() override;
void RestoreAPIState() override;

View File

@ -48,6 +48,7 @@ Make AA apply instantly during gameplay if possible
#include "Core/Core.h"
#include "Core/Host.h"
#include "VideoBackends/OGL/BoundingBox.h"
#include "VideoBackends/OGL/FramebufferManager.h"
#include "VideoBackends/OGL/GLInterfaceBase.h"
#include "VideoBackends/OGL/GLUtil.h"
@ -205,6 +206,7 @@ void VideoBackend::Video_Prepare()
Renderer::Init();
VertexLoaderManager::Init();
TextureConverter::Init();
BoundingBox::Init();
// Notify the core that the video backend is ready
Host_Message(WM_USER_CREATE);
@ -229,6 +231,7 @@ void VideoBackend::Video_Cleanup()
// The following calls are NOT Thread Safe
// And need to be called from the video thread
Renderer::Shutdown();
BoundingBox::Shutdown();
TextureConverter::Shutdown();
VertexLoaderManager::Shutdown();
delete g_sampler_cache;