Made ImGui to work with the Vulkan builds

This commit is contained in:
Robert Beckebans 2020-05-04 17:22:51 +02:00
parent 33a232a840
commit 14a331fadd
8 changed files with 166 additions and 52 deletions

View file

@ -56,7 +56,7 @@ I started this project in 2012 and focused on making this code being future proo
* Changed light interaction shaders to use Half-Lambert lighting like in Half-Life 2 to
make the game less dark. https://developer.valvesoftware.com/wiki/Half_Lambert
* True internal 64 bit HDR lighting with filmic ACES tone mapping and gamma-correct rendering in linear RGB space
* Enhanced Subpixel Morphological Antialiasing. For more information see "Anti-Aliasing Methods in CryENGINE 3" and the docs at http://www.iryoku.com/smaa/
* Enhanced Subpixel Morphological Antialiasing as a cheap alternative for MSAA. For more information see "Anti-Aliasing Methods in CryENGINE 3" and the docs at http://www.iryoku.com/smaa/
* Filmic post process effects like Chromatic Aberration and Dithering
* Additional ambient render pass to make the game less dark similar to the Quake 4 r_forceAmbient technique
* Screen Space Ambient Occlusion http://graphics.cs.williams.edu/papers/SAOHPG12/
@ -135,11 +135,11 @@ Left: No post processing except HDR tone mapping. Right: r_useFilmicPostProcessi
* ~~Fix GPU Skinning with Vulkan~~
* ~~Fix the lighting with stencil shadows with Vulkan~~
* ~~Finish adapting the Vulkan renderer backend based on Dustin Land's vkDOOM3~~
* Port all the RBDOOM-3-BFG specific extras like HDR, Shadow Mapping and Post Processing to Vulkan
* ~~Use ImGui to show renderer stats like com_showFPS 1 and more detailed renderer stats~~
* Get ImGui to run with Vulkan and visualize the Vulkan memory fragmentation based on AMD's VMA library
* Finish PBR texture support
* ~~Get ImGui to run with Vulkan~~
* Visualize the Vulkan memory fragmentation based on AMD's VMA library with ImGui
* Port all the RBDOOM-3-BFG specific extras like HDR, Shadow Mapping and Post Processing to Vulkan
* ~~Finish PBR texture support~~
* Finish partly integrated IBL lighting and [Light probe interpolation using tetrahedral tessellations](https://gdcvault.com/play/1015312/Light-Probe-Interpolation-Using-Tetrahedral)
* Generate IBL probes on the GPU through compute shaders
* Add Screen Space Reflections

View file

@ -67,6 +67,8 @@ The main goal is that the new content looks the same in RBDOOM-3-BFG as in Blend
* Fixed Bink video playback with Vulkan
* ImGui runs with Vulkan by skipping all Vulkan implementation details for it and rendering ImGui on a higher level like the Flash GUI
[MISCELLANEOUS]
* com_showFPS 1 uses ImGui to show more detailed renderer stats like the console prints with r_speeds

View file

@ -209,16 +209,16 @@ void idConsoleLocal::DrawTextRightAlign( float x, float& y, const char* text, ..
idConsoleLocal::DrawFPS
==================
*/
#define FPS_FRAMES 6
#define FPS_FRAMES 90
float idConsoleLocal::DrawFPS( float y )
{
static int previousTimes[FPS_FRAMES];
static float previousTimes[FPS_FRAMES];
static float previousTimesNormalized[FPS_FRAMES];
static int index;
static int previous;
static int valuesOffset = 0;
#if !defined( USE_VULKAN )
bool renderImGuiPerfWindow = ImGuiHook::IsReadyToRender() && ( com_showFPS.GetInteger() == 1 );
#endif
// don't use serverTime, because that will be drifting to
// correct for internet lag changes, timescales, timedemos, etc
@ -228,7 +228,11 @@ float idConsoleLocal::DrawFPS( float y )
int fps = 0;
const float milliSecondsPerFrame = 1000.0f / com_engineHz_latched;
previousTimes[index % FPS_FRAMES] = frameTime;
previousTimesNormalized[index % FPS_FRAMES] = frameTime / milliSecondsPerFrame;
valuesOffset = ( valuesOffset + 1 ) % FPS_FRAMES;
index++;
if( index > FPS_FRAMES )
{
@ -248,14 +252,10 @@ float idConsoleLocal::DrawFPS( float y )
const char* s = va( "%ifps", fps );
int w = strlen( s ) * BIGCHAR_WIDTH;
#if defined( USE_VULKAN )
renderSystem->DrawBigStringExt( LOCALSAFE_RIGHT - w, idMath::Ftoi( y ) + 2, s, colorWhite, true );
#else
if( com_showFPS.GetInteger() == 2 )
{
renderSystem->DrawBigStringExt( LOCALSAFE_RIGHT - w, idMath::Ftoi( y ) + 2, s, colorWhite, true );
}
#endif
}
y += BIGCHAR_HEIGHT + 4;
@ -281,14 +281,13 @@ float idConsoleLocal::DrawFPS( float y )
const uint64 rendererGPUTime = commonLocal.GetRendererGPUMicroseconds();
const int maxTime = 16 * 1000;
#if !defined( USE_VULKAN )
#if 1
// RB: use ImGui to show more detailed stats about the scene loads
if( ImGuiHook::IsReadyToRender() )
{
int32 statsWindowWidth = 550;
int32 statsWindowHeight = 290;
int32 statsWindowHeight = 320; // 290 without the frame plot
ImVec2 pos;
pos.x = renderSystem->GetWidth() - statsWindowWidth;
@ -297,40 +296,83 @@ float idConsoleLocal::DrawFPS( float y )
ImGui::SetNextWindowPos( pos );
ImGui::SetNextWindowSize( ImVec2( statsWindowWidth, statsWindowHeight ) );
static ImVec4 colorBlack = ImVec4( 0.00f, 0.00f, 0.00f, 1.00f );
static ImVec4 colorWhite = ImVec4( 1.00f, 1.00f, 1.00f, 1.00f );
static ImVec4 colorRed = ImVec4( 1.00f, 0.00f, 0.00f, 1.00f );
static ImVec4 colorGreen = ImVec4( 0.00f, 1.00f, 0.00f, 1.00f );
static ImVec4 colorBlue = ImVec4( 0.00f, 0.00f, 1.00f, 1.00f );
static ImVec4 colorYellow = ImVec4( 1.00f, 1.00f, 0.00f, 1.00f );
static ImVec4 colorMagenta = ImVec4( 1.00f, 0.00f, 1.00f, 1.00f );
static ImVec4 colorCyan = ImVec4( 0.00f, 1.00f, 1.00f, 1.00f );
static ImVec4 colorOrange = ImVec4( 1.00f, 0.50f, 0.00f, 1.00f );
static ImVec4 colorPurple = ImVec4( 0.60f, 0.00f, 0.60f, 1.00f );
static ImVec4 colorPink = ImVec4( 0.73f, 0.40f, 0.48f, 1.00f );
static ImVec4 colorBrown = ImVec4( 0.40f, 0.35f, 0.08f, 1.00f );
static ImVec4 colorLtGrey = ImVec4( 0.75f, 0.75f, 0.75f, 1.00f );
static ImVec4 colorMdGrey = ImVec4( 0.50f, 0.50f, 0.50f, 1.00f );
static ImVec4 colorDkGrey = ImVec4( 0.25f, 0.25f, 0.25f, 1.00f );
ImGui::Begin( "Performance Stats" );
//ImGui::Text( "Render API: OpenGL" );
#if defined( USE_VULKAN )
const char* API = "Vulkan";
#else
const char* API = "OpenGL";
#endif
ImGui::TextColored( ImVec4( 0.00f, 1.00f, 0.00f, 1.00f ), "GENERAL: views:%i draws:%i tris:%i (shdw:%i)",
extern idCVar r_antiAliasing;
static const int aaNumValues = 5;
static const char* aaValues[aaNumValues] =
{
"None",
"SMAA 1X",
"MSAA 2X",
"MSAA 4X",
"MSAA 8X"
};
compile_time_assert( aaNumValues == ( ANTI_ALIASING_MSAA_8X + 1 ) );
const char* aaMode = aaValues[ r_antiAliasing.GetInteger() ];
idStr resolutionText;
resolutionScale.GetConsoleText( resolutionText );
int width = renderSystem->GetWidth();
int height = renderSystem->GetHeight();
ImGui::TextColored( colorGreen, "API: %s, AA[%i, %i]: %s, %s", API, width, height, aaMode, resolutionText.c_str() );
ImGui::TextColored( colorYellow, "GENERAL: views:%i draws:%i tris:%i (shdw:%i)",
commonLocal.stats_frontend.c_numViews,
commonLocal.stats_backend.c_drawElements + commonLocal.stats_backend.c_shadowElements,
( commonLocal.stats_backend.c_drawIndexes + commonLocal.stats_backend.c_shadowIndexes ) / 3,
commonLocal.stats_backend.c_shadowIndexes / 3 );
ImGui::Text( "DYNAMIC: callback:%i md5:%i dfrmVerts:%i dfrmTris:%i tangTris:%i guis:%i",
commonLocal.stats_frontend.c_entityDefCallbacks,
commonLocal.stats_frontend.c_generateMd5,
commonLocal.stats_frontend.c_deformedVerts,
commonLocal.stats_frontend.c_deformedIndexes / 3,
commonLocal.stats_frontend.c_tangentIndexes / 3,
commonLocal.stats_frontend.c_guiSurfs
);
ImGui::TextColored( colorLtGrey, "DYNAMIC: callback:%i md5:%i dfrmVerts:%i dfrmTris:%i tangTris:%i guis:%i",
commonLocal.stats_frontend.c_entityDefCallbacks,
commonLocal.stats_frontend.c_generateMd5,
commonLocal.stats_frontend.c_deformedVerts,
commonLocal.stats_frontend.c_deformedIndexes / 3,
commonLocal.stats_frontend.c_tangentIndexes / 3,
commonLocal.stats_frontend.c_guiSurfs
);
//ImGui::Text( "Cull: %i box in %i box out\n",
// commonLocal.stats_frontend.c_box_cull_in, commonLocal.stats_frontend.c_box_cull_out );
ImGui::Text( "ADDMODEL: callback:%i createInteractions:%i createShadowVolumes:%i",
commonLocal.stats_frontend.c_entityDefCallbacks,
commonLocal.stats_frontend.c_createInteractions,
commonLocal.stats_frontend.c_createShadowVolumes );
ImGui::TextColored( colorLtGrey, "ADDMODEL: callback:%i createInteractions:%i createShadowVolumes:%i",
commonLocal.stats_frontend.c_entityDefCallbacks,
commonLocal.stats_frontend.c_createInteractions,
commonLocal.stats_frontend.c_createShadowVolumes );
ImGui::Text( "viewEntities:%i shadowEntities:%i viewLights:%i\n", commonLocal.stats_frontend.c_visibleViewEntities,
commonLocal.stats_frontend.c_shadowViewEntities,
commonLocal.stats_frontend.c_viewLights );
ImGui::TextColored( colorLtGrey, "viewEntities:%i shadowEntities:%i viewLights:%i\n", commonLocal.stats_frontend.c_visibleViewEntities,
commonLocal.stats_frontend.c_shadowViewEntities,
commonLocal.stats_frontend.c_viewLights );
ImGui::Text( "UPDATES: entityUpdates:%i entityRefs:%i lightUpdates:%i lightRefs:%i\n",
commonLocal.stats_frontend.c_entityUpdates, commonLocal.stats_frontend.c_entityReferences,
commonLocal.stats_frontend.c_lightUpdates, commonLocal.stats_frontend.c_lightReferences );
ImGui::TextColored( colorLtGrey, "UPDATES: entityUpdates:%i entityRefs:%i lightUpdates:%i lightRefs:%i\n",
commonLocal.stats_frontend.c_entityUpdates, commonLocal.stats_frontend.c_entityReferences,
commonLocal.stats_frontend.c_lightUpdates, commonLocal.stats_frontend.c_lightReferences );
//ImGui::Text( "frameData: %i (%i)\n", frameData->frameMemoryAllocated.GetValue(), frameData->highWaterAllocated );
@ -338,12 +380,16 @@ float idConsoleLocal::DrawFPS( float y )
ImGui::Spacing();
ImGui::Spacing();
ImGui::TextColored( ImVec4( 0.00f, 1.00f, 1.00f, 1.00f ), "Average FPS %i", fps );
//ImGui::TextColored( colorCyan, "Average FPS %i", fps );
{
const char* overlay = va( "Average FPS %i", fps );
ImGui::PlotLines( "Relative\nFrametime ms", previousTimesNormalized, FPS_FRAMES, valuesOffset, overlay, -10.0f, 10.0f, ImVec2( 0, 50 ) );
}
ImGui::Spacing();
ImVec4 colorWhite( 1.0f, 1.0f, 1.0f, 1.0f );
ImVec4 colorRed( 1.0f, 0.0f, 0.0f, 1.0f );
ImGui::TextColored( gameThreadTotalTime > maxTime ? colorRed : colorWhite, "G+RF: %5llu us", gameThreadTotalTime );
ImGui::TextColored( gameThreadGameTime > maxTime ? colorRed : colorWhite, "G: %5llu us", gameThreadGameTime );
@ -355,7 +401,6 @@ float idConsoleLocal::DrawFPS( float y )
ImGui::End();
}
#endif
return y;
#else

View file

@ -5413,8 +5413,11 @@ void idRenderBackend::ExecuteBackEndCommands( const emptyCommand_t* cmds )
break;
case RC_POST_PROCESS:
{
// apply optional post processing
PostProcess( cmds );
break;
}
default:
common->Error( "RB_ExecuteBackEndCommands: bad commandId" );
@ -5424,9 +5427,6 @@ void idRenderBackend::ExecuteBackEndCommands( const emptyCommand_t* cmds )
DrawFlickerBox();
// RB
//ImGuiHook::Render();
GL_EndFrame();
// stop rendering on this thread
@ -6129,5 +6129,5 @@ void idRenderBackend::PostProcess( const void* data )
#endif
renderLog.CloseBlock();
//renderLog.CloseBlock();
}

View file

@ -838,6 +838,7 @@ public:
const idMaterial* whiteMaterial;
const idMaterial* charSetMaterial;
const idMaterial* imgGuiMaterial; // RB
const idMaterial* defaultPointLight;
const idMaterial* defaultProjectedLight;
const idMaterial* defaultMaterial;

View file

@ -653,8 +653,10 @@ void idRenderSystemLocal::SwapCommandBuffers_FinishRendering(
// After coming back from an autoswap, we won't have anything to render
//if( frameData && frameData->cmdHead->next != NULL )
{
#if !defined( USE_VULKAN )
// RB: FIXME move this elsewhere
ImGuiHook::Render();
#endif
// wait for our fence to hit, which means the swap has actually happened
// We must do this before clearing any resources the GPU may be using
@ -735,6 +737,12 @@ const emptyCommand_t* idRenderSystemLocal::SwapCommandBuffers_FinishCommandBuffe
return NULL;
}
// RB: general GUI system path to treat ImGui surfaces in the renderer frontend like SWF
// this calls io.RenderDrawListsFn
#if defined( USE_VULKAN )
ImGuiHook::Render();
#endif
// close any gui drawing
guiModel->EmitFullScreen();
guiModel->Clear();

View file

@ -2066,6 +2066,9 @@ void R_InitMaterials()
tr.defaultProjectedLight = declManager->FindMaterial( "lights/defaultProjectedLight" );
tr.whiteMaterial = declManager->FindMaterial( "_white" );
tr.charSetMaterial = declManager->FindMaterial( "textures/bigchars" );
// RB: create implicit material
tr.imgGuiMaterial = declManager->FindMaterial( "_imguiFont", true );
}

View file

@ -2690,22 +2690,77 @@ IMGUI RENDERING
void idRenderBackend::ImGui_Init()
{
// TODO
// not needed
}
void idRenderBackend::ImGui_Shutdown()
{
// TODO
//ImGui::GetIO().Fonts->TexID = 0;
// not needed
}
// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure)
// If text or lines are blurry when integrating ImGui in your engine:
// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f)
// TODO move this out of the renderer backend for Vulkan because it is called in the renderer frontend
// NOTE: this implementation does not support scissor clipping for the indivudal draw commands
// but it is sufficient for things like com_showFPS
void idRenderBackend::ImGui_RenderDrawLists( ImDrawData* draw_data )
{
// TODO
renderProgManager.Unbind();
const float sysWidth = renderSystem->GetWidth();
const float sysHeight = renderSystem->GetHeight();
idVec2 scaleToVirtual( ( float )renderSystem->GetVirtualWidth() / sysWidth, ( float )renderSystem->GetVirtualHeight() / sysHeight );
for( int a = 0; a < draw_data->CmdListsCount; a++ )
{
const ImDrawList* cmd_list = draw_data->CmdLists[a];
const ImDrawIdx* indexBufferOffset = &cmd_list->IdxBuffer.front();
int numVerts = cmd_list->VtxBuffer.size();
for( int b = 0; b < cmd_list->CmdBuffer.size(); b++ )
{
const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[b];
int numIndexes = pcmd->ElemCount;
// TODO support more than just the imGui Font texture
// but we can live with the current solution because ImGui is only meant to draw a few bars and timers
//glBindTexture( GL_TEXTURE_2D, ( GLuint )( intptr_t )pcmd->TextureId )
//const idMaterial* material = declManager->FindMaterial( texture name of pcmd->TextureId );
idDrawVert* verts = renderSystem->AllocTris( numVerts, indexBufferOffset, numIndexes, tr.imgGuiMaterial, STEREO_DEPTH_TYPE_NONE );
if( verts == NULL )
{
continue;
}
if( pcmd->UserCallback )
{
pcmd->UserCallback( cmd_list, pcmd );
}
else
{
for( int j = 0; j < numVerts; j++ )
{
const ImDrawVert* imVert = &cmd_list->VtxBuffer[j];
ALIGNTYPE16 idDrawVert tempVert;
//tempVert.xyz = idVec3( imVert->pos.x, imVert->pos.y, 0.0f );
tempVert.xyz.ToVec2() = idVec2( imVert->pos.x, imVert->pos.y ).Scale( scaleToVirtual );
tempVert.xyz.z = 0.0f;
tempVert.SetTexCoord( imVert->uv.x, imVert->uv.y );
tempVert.SetColor( imVert->col );
WriteDrawVerts16( &verts[j], &tempVert, 1 );
}
}
indexBufferOffset += pcmd->ElemCount;
}
}
}