Files
Webcam/include/engine/gpu/gpu_video.cpp

329 lines
9.8 KiB
C++

/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#include "gpu/gpu_renderer.h"
#include "log/log.h"
using namespace GS::GPU;
//------------------------------------------------------------------------------
Renderer::RenderTechnique Renderer::GetDefaultRenderTechnique() const
{
String technique = registry.GetString("Technique", "Forward");
if (technique == "Deferred")
return TechniqueDeferred;
return TechniqueForward;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void Renderer::FreeRenderTechnique()
{
for (uint n = 0; n < 4; ++n)
t_gbuffer[n] = NULL;
t_depth = NULL;
t_color_aa = NULL;
t_depth_aa = NULL;
}
void Renderer::SetRenderTechnique(RenderTechnique p)
{
if (p == TechniqueDefault)
p = GetDefaultRenderTechnique();
// Filter out illegal configurations.
if (!gpu_config.use_rtt && (p == TechniqueDeferred))
p = TechniqueForward;
FreeRenderTechnique();
render_technique = p;
// Select AA method.
Render::Texture::AA aa = Render::Texture::NoAA;
if ((p == TechniqueForward) && gpu_config.can_resolve_msaa)
if (registry.GetBool("Antialiasing:Enable", false))
{
float sample = registry.GetReal("Antialiasing:Sample", 4.0);
if (sample > 8.f) aa = Render::Texture::MSAA16x;
else if (sample > 4.f) aa = Render::Texture::MSAA8x;
else if (sample > 2.f) aa = Render::Texture::MSAA4x;
else if (sample > 1.f) aa = Render::Texture::MSAA2x;
}
gpu_config.enable_aa = asbool(aa != Render::Texture::NoAA);
// Setup technique objects.
__LOG__ << "SetRenderTechnique(): " << dimensions.x << "x" << dimensions.y << "\n";
bool use_float = registry.GetBool("Texture:Float:Enable", false);
Render::Texture::Format t_format = use_float ? Render::Texture::FormatRGBAF : Render::Texture::FormatRGBA8;
for (uint n = 0; n < 2; ++n)
{
t_compose[n] = NewTexture(String("t_compose") << n);
t_compose[n]->Create(NULL, dimensions.x, dimensions.y, t_format, Render::Texture::NoAA, Render::Texture::Usage(Render::Texture::IsRenderTarget | Render::Texture::IsShaderResource));
t_compose[n]->SetFiltering(Render::TextureParm::FilterTrilinear);
t_compose[n]->SetWrapping(Render::TextureParm::WrapClamp, Render::TextureParm::WrapClamp);
}
switch (p)
{
case TechniqueForward:
{
if (gpu_config.can_resolve_msaa)
{
t_color_aa = NewTexture("t_color_aa");
t_color_aa->Create(NULL, dimensions.x, dimensions.y, t_format, aa, Render::Texture::Usage(Render::Texture::IsRenderTarget | Render::Texture::IsShaderResource));
t_depth_aa = NewTexture("t_depth_aa");
t_depth_aa->Create(NULL, dimensions.x, dimensions.y, Render::Texture::FormatDepth, aa, Render::Texture::Usage(Render::Texture::IsRenderTarget | Render::Texture::IsShaderResource));
buffer_fbo->SetColorTexture(t_color_aa);
buffer_fbo->SetDepthTexture(t_depth_aa);
}
if (gpu_config.use_rtt)
{
t_depth = NewTexture("t_depth");
t_depth->Create(NULL, dimensions.x, dimensions.y, Render::Texture::FormatDepth, Render::Texture::NoAA, Render::Texture::Usage(Render::Texture::IsRenderTarget | Render::Texture::IsShaderResource));
resolve_fbo->SetColorTexture(t_compose[0]);
resolve_fbo->SetDepthTexture(t_depth);
}
}
break;
case TechniqueDeferred:
{
for (uint n = 0; n < 4; ++n)
{
t_gbuffer[n] = NewTexture(String("t_gbuffer") << n);
t_gbuffer[n]->Create(NULL, dimensions.x, dimensions.y, Render::Texture::FormatRGBAF, Render::Texture::NoAA, Render::Texture::Usage(Render::Texture::IsRenderTarget | Render::Texture::IsShaderResource));
t_gbuffer[n]->SetFiltering(Render::TextureParm::FilterNearest);
}
t_depth = NewTexture("t_depth");
t_depth->Create(NULL, dimensions.x, dimensions.y, Render::Texture::FormatDepth, Render::Texture::NoAA, Render::Texture::Usage(Render::Texture::IsRenderTarget | Render::Texture::IsShaderResource));
Render::Texture *rt[4] = { t_gbuffer[0], t_gbuffer[1], t_gbuffer[2], t_gbuffer[3] };
buffer_fbo->SetColorTexture(rt, 4);
buffer_fbo->SetDepthTexture(t_depth);
resolve_fbo->SetColorTexture(t_compose[0]);
resolve_fbo->SetDepthTexture(t_depth);
}
break;
}
SetPostProcess();
}
void Renderer::SetPostProcess(uint k)
{
if (!gpu_config.use_rtt)
return;
if (k == 0)
k = registry.GetInteger("PostProcess:FX:Scale", 4);
for (uint n = 0; n < 3; ++n)
{
t_fx[n] = NewTexture(String("t_fx") << n);
t_fx[n]->Create(NULL, dimensions.x / k, dimensions.y / k, Render::Texture::FormatRGBAF, Render::Texture::NoAA, Render::Texture::Usage(Render::Texture::IsRenderTarget | Render::Texture::IsShaderResource));
t_fx[n]->SetFiltering(Render::TextureParm::FilterBilinear);
t_fx[n]->SetWrapping(Render::TextureParm::WrapClamp, Render::TextureParm::WrapClamp);
}
t_fx_depth = NewTexture("t_fx_depth");
t_fx_depth->Create(NULL, dimensions.x / k, dimensions.y / k, Render::Texture::FormatDepth, Render::Texture::NoAA, Render::Texture::Usage(Render::Texture::IsRenderTarget | Render::Texture::IsShaderResource));
t_fx_depth->SetFiltering(Render::TextureParm::FilterNearest);
t_fx_depth->SetWrapping(Render::TextureParm::WrapClamp, Render::TextureParm::WrapClamp);
fx_scale = k;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
bool Renderer::SetupCoreResources(bool support_3d)
{
// Core shaders & objects.
if (!LoadCoreShaders(support_3d))
return false;
resolve_fbo = NewFBO();
resolve_fbo->Create();
if (support_3d)
{
buffer_fbo = NewFBO();
buffer_fbo->Create();
fx_fbo = NewFBO();
fx_fbo->Create();
// Shadow mapping objects.
if (gpu_config.enable_shadow)
{
shadow_map_fbo = NewFBO();
shadow_map_fbo->Create();
CreateShadowMaps();
}
// Default technique.
SetRenderTechnique();
if (!CreateTerrainPatch())
return false;
t_noise = core_resource_factory->LoadTexture("@core/noise.tga");
}
{
static const ushort idx[] = { 2, 1, 0, 3, 2, 0 };
static const float vtx[] = { -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, 1, 1 };
skybox_idx_vbo = NewVBO();
skybox_idx_vbo->Create(idx, sizeof(ushort) * 6, VBO::Index);
skybox_vtx_vbo = NewVBO();
skybox_vtx_vbo->Create(vtx, sizeof(float) * 3 * 4, VBO::Vertex);
helper_idx_vbo = NewVBO();
helper_idx_vbo->Create(idx, sizeof(ushort) * 6, VBO::Index);
helper_vtx_vbo = NewVBO();
helper_vtx_vbo->Create(sizeof(float) * 256, VBO::Vertex, VBO::Dynamic); // 1Kb WARNING watch out for possible overflow when updating this buffer!
ushort box_idx[] =
{
0, 1, 2, 0, 2, 3, 1, 5, 6, 1, 6, 2,
5, 4, 7, 5, 7, 6, 4, 0, 3, 4, 3, 7,
4, 5, 1, 4, 1, 0, 3, 2, 6, 3, 6, 7
};
box_idx_vbo = NewVBO();
box_idx_vbo->Create(box_idx, sizeof(ushort) * 3 * 4 * 3, VBO::Index);
direct_idx_vbo = NewVBO();
direct_vtx_vbo = NewVBO();
}
return true;
}
void Renderer::SetDefaultStates()
{
// Set defaults states.
EnableDepthTest(true);
SetDepthFunc(DepthLess);
EnableCulling(true);
SetCullFunc(CullFront);
EnableBlending(false);
SetBlendFunc(BlendSrcAlpha, BlendOneMinusSrcAlpha);
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void Renderer::DiscoverGPUConfiguration()
{
Variant v;
if (QueryCaps(CanBlitRBO, v))
gpu_config.can_resolve_msaa = v.b_value;
if (QueryCaps(MaxAnisotropy, v))
gpu_config.max_anisotropy = v.i_value;
if (QueryCaps(TextureTopLeftOrigin, v))
gpu_config.tex_origin_is_top_left = v.b_value;
#if __PLATFORM_ANDROID_NDK__ || __PLATFORM_IOS__ || __PLATFORM_EMSCRIPTEN__
// Drop all advanced features... for now.
gpu_config.enable_shadow = false;
gpu_config.can_resolve_msaa = false;
gpu_config.use_rtt = false;
gpu_config.npot = RendererConfig::NPOT_Limited;
#endif
if (!gpu_config.can_resolve_msaa)
__LOG_W__ << "Insufficient RBO support, falling back to RTT: No hardware MSAA.\n";
if (!gpu_config.enable_shadow)
__LOG_W__ << "Shadow-mapping support disabled.\n";
if (gpu_config.npot == RendererConfig::NPOT_Limited)
__LOG_V__ << "NPOT limited support.\n";
if (gpu_config.npot == RendererConfig::NPOT_Full)
__LOG_V__ << "NPOT full support.\n";
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
bool Renderer::ResizeVideo(uint w, uint h)
{
__LOG_V__ << "GPU Resize video to " << w << "x" << h << ".\n";
dimensions.Set(w, h);
SetRenderTechnique(render_technique);
return true;
}
bool Renderer::Open(uint w, uint h, char bpp, GS::Render::VideoMode mode, const void *sys_handle)
{
if (!OpenPlatformVideo(w, h, bpp, mode, sys_handle))
return false;
if (!InitializePlatform())
return false;
__LOG__ << "\n";
__LOG_H__ << "GPU-based (" << GetName() << ") on adapter " << stats.adapter << " (vendor: " << stats.vendor << ").\n";
__LOG__ << "\n";
DiscoverGPUConfiguration();
dimensions.Set(w, h);
SetViewport(fRect(0, 0, (float)w, (float)h));
return true;
}
void Renderer::Free()
{
__LOG_FUNC__
terrain_patch_cache.Free();
FreeRenderTechnique();
helper_idx_vbo = NULL;
helper_vtx_vbo = NULL;
skybox_idx_vbo = NULL;
skybox_vtx_vbo = NULL;
direct_idx_vbo = NULL;
direct_vtx_vbo = NULL;
box_idx_vbo = NULL;
buffer_fbo = NULL;
resolve_fbo = NULL;
fx_fbo = NULL;
for (uint n = 0; n < 2; ++n)
t_compose[n] = NULL;
for (uint n = 0; n < 3; ++n)
t_fx[n] = NULL;
t_fx_depth = NULL;
fx_scale = 0;
t_noise = NULL;
FreeShadowMaps();
shadow_map_fbo = NULL;
UnloadCoreShaders();
}
void Renderer::Close()
{
Free();
ClosePlatformVideo();
}
//------------------------------------------------------------------------------