GL_State cleanup. Fixed most GUI rendering problems

This commit is contained in:
Robert Beckebans 2022-03-16 12:20:58 +01:00
parent 0eb9b97471
commit 24853acc45
5 changed files with 191 additions and 552 deletions

View file

@ -1024,6 +1024,7 @@ void idImage::GenerateImage( const byte* pic, int width, int height, textureFilt
{
const bimageImage_t& img = im.GetImageHeader( i );
const byte* data = im.GetImageData( i );
int rowPitch = GetRowPitch( opts.format, img.width );
commandList->writeTexture( texture, img.destZ, img.level, data, rowPitch );
}
@ -1112,11 +1113,7 @@ void idImage::GenerateCubeImage( const byte* pic[6], int size, textureFilter_t f
{
const bimageImage_t& img = im.GetImageHeader( i );
const byte* data = im.GetImageData( i );
int bufferW = img.width;
if( IsCompressed() )
{
bufferW = ( img.width + 3 ) & ~3;
}
commandList->writeTexture( texture, 0, img.level, data, GetRowPitch( opts.format, img.width ) );
}

View file

@ -96,64 +96,10 @@ GL_CheckErrors
// RB: added filename, line parms
bool GL_CheckErrors_( const char* filename, int line )
{
int err;
char s[64];
int i;
if( r_ignoreGLErrors.GetBool() )
{
return false;
}
// check for up to 10 errors pending
bool error = false;
for( i = 0 ; i < 10 ; i++ )
{
err = glGetError();
if( err == GL_NO_ERROR )
{
break;
}
error = true;
switch( err )
{
case GL_INVALID_ENUM:
strcpy( s, "GL_INVALID_ENUM" );
break;
case GL_INVALID_VALUE:
strcpy( s, "GL_INVALID_VALUE" );
break;
case GL_INVALID_OPERATION:
strcpy( s, "GL_INVALID_OPERATION" );
break;
#if !defined(USE_GLES2) && !defined(USE_GLES3)
case GL_STACK_OVERFLOW:
strcpy( s, "GL_STACK_OVERFLOW" );
break;
case GL_STACK_UNDERFLOW:
strcpy( s, "GL_STACK_UNDERFLOW" );
break;
#endif
case GL_OUT_OF_MEMORY:
strcpy( s, "GL_OUT_OF_MEMORY" );
break;
default:
idStr::snPrintf( s, sizeof( s ), "%i", err );
break;
}
common->Printf( "caught OpenGL error: %s in file %s line %i\n", s, filename, line );
}
return error;
return false;
}
/*
========================
DebugCallback
@ -661,6 +607,16 @@ void idRenderBackend::DrawElementsWithCounters( const drawSurf_t* surf )
int program = renderProgManager.CurrentProgram();
int bindingLayoutType = renderProgManager.BindingLayoutType();
auto& info = renderProgManager.GetProgramInfo( program );
/*
if( info.cs )
{
renderLog.OpenBlock( info.cs->getDesc().debugName.c_str() );
}
else
{
renderLog.OpenBlock( info.ps->getDesc().debugName.c_str() );
}
*/
for( int i = 0; i < info.bindingLayouts->Num(); i++ )
{
@ -673,7 +629,7 @@ void idRenderBackend::DrawElementsWithCounters( const drawSurf_t* surf )
renderProgManager.CommitConstantBuffer( commandList );
PipelineKey key{ glStateBits, program, viewDef->isMirror, depthBias, slopeScaleBias, currentFrameBuffer };
PipelineKey key{ glStateBits, program, depthBias, slopeScaleBias, currentFrameBuffer };
auto pipeline = pipelineCache.GetOrCreatePipeline( key );
if( currentPipeline != pipeline )
@ -722,6 +678,8 @@ void idRenderBackend::DrawElementsWithCounters( const drawSurf_t* surf )
// RB: added stats
pc.c_drawElements++;
pc.c_drawIndexes += surf->numIndexes;
//renderLog.CloseBlock();
}
void idRenderBackend::GetCurrentBindingLayout()
@ -970,24 +928,14 @@ void idRenderBackend::GL_SetDefaultState()
memset( &glcontext.tmu, 0, sizeof( glcontext.tmu ) );
glStateBits = 0;
currentRenderState.depthStencilState.enableDepthWrite();
currentRenderState.depthStencilState.enableStencil();
GL_State( 0, true );
currentRenderState.depthStencilState.enableDepthTest();
currentRenderState.blendState.targets[0].enableBlend();
if( r_useScissor.GetBool() )
{
GL_Scissor( 0, 0, renderSystem->GetWidth(), renderSystem->GetHeight() );
}
GL_Scissor( 0, 0, renderSystem->GetWidth(), renderSystem->GetHeight() );
renderProgManager.Unbind();
// RB begin
Framebuffer::Unbind();
// RB end
}
/*
@ -999,397 +947,13 @@ This routine is responsible for setting the most commonly changed state
*/
void idRenderBackend::GL_State( uint64 stateBits, bool forceGlState )
{
uint64 diff = stateBits ^ glStateBits;
if( !r_useStateCaching.GetBool() || forceGlState )
glStateBits = stateBits | ( glStateBits & GLS_KEEP );
if( viewDef != NULL && viewDef->isMirror )
{
// make sure everything is set all the time, so we
// can see if our delta checking is screwing up
diff = 0xFFFFFFFFFFFFFFFF;
}
else if( diff == 0 )
{
return;
glStateBits |= GLS_MIRROR_VIEW;
}
// Reset pipeline
currentPipeline = nullptr;
auto& currentBlendState = currentRenderState.blendState;
auto& currentDepthStencilState = currentRenderState.depthStencilState;
auto& currentRasterState = currentRenderState.rasterState;
//
// culling
//
if( diff & ( GLS_CULL_BITS ) )//| GLS_MIRROR_VIEW ) )
{
switch( stateBits & GLS_CULL_BITS )
{
case GLS_CULL_TWOSIDED:
currentRasterState.setCullNone();
break;
case GLS_CULL_BACKSIDED:
if( viewDef != NULL && viewDef->isMirror )
{
stateBits |= GLS_MIRROR_VIEW;
currentRasterState.setCullFront();
}
else
{
currentRasterState.setCullBack();
}
break;
case GLS_CULL_FRONTSIDED:
default:
if( viewDef != NULL && viewDef->isMirror )
{
stateBits |= GLS_MIRROR_VIEW;
currentRasterState.setCullBack();
}
else
{
currentRasterState.setCullFront();
}
break;
}
}
//
// check depthFunc bits
//
if( diff & GLS_DEPTHFUNC_BITS )
{
switch( stateBits & GLS_DEPTHFUNC_BITS )
{
case GLS_DEPTHFUNC_EQUAL:
currentDepthStencilState.depthFunc = nvrhi::ComparisonFunc::Equal;
break;
case GLS_DEPTHFUNC_ALWAYS:
currentDepthStencilState.depthFunc = nvrhi::ComparisonFunc::Always;
break;
case GLS_DEPTHFUNC_LESS:
currentDepthStencilState.depthFunc = nvrhi::ComparisonFunc::Less;
break;
case GLS_DEPTHFUNC_GREATER:
currentDepthStencilState.depthFunc = nvrhi::ComparisonFunc::Greater;
break;
}
}
nvrhi::BlendState::RenderTarget renderTarget;
//
// check blend bits
//
if( diff & ( GLS_SRCBLEND_BITS | GLS_DSTBLEND_BITS ) )
{
nvrhi::BlendFactor srcFactor = nvrhi::BlendFactor::One;
nvrhi::BlendFactor dstFactor = nvrhi::BlendFactor::One;
switch( stateBits & GLS_SRCBLEND_BITS )
{
case GLS_SRCBLEND_ZERO:
srcFactor = nvrhi::BlendFactor::Zero;
break;
case GLS_SRCBLEND_ONE:
srcFactor = nvrhi::BlendFactor::One;
break;
case GLS_SRCBLEND_DST_COLOR:
srcFactor = nvrhi::BlendFactor::DstColor;
break;
case GLS_SRCBLEND_ONE_MINUS_DST_COLOR:
srcFactor = nvrhi::BlendFactor::OneMinusDstColor;
break;
case GLS_SRCBLEND_SRC_ALPHA:
srcFactor = nvrhi::BlendFactor::SrcAlpha;
break;
case GLS_SRCBLEND_ONE_MINUS_SRC_ALPHA:
srcFactor = nvrhi::BlendFactor::OneMinusSrcAlpha;
break;
case GLS_SRCBLEND_DST_ALPHA:
srcFactor = nvrhi::BlendFactor::DstAlpha;
break;
case GLS_SRCBLEND_ONE_MINUS_DST_ALPHA:
srcFactor = nvrhi::BlendFactor::OneMinusDstAlpha;
break;
default:
assert( !"GL_State: invalid src blend state bits\n" );
break;
}
switch( stateBits & GLS_DSTBLEND_BITS )
{
case GLS_DSTBLEND_ZERO:
dstFactor = nvrhi::BlendFactor::Zero;
break;
case GLS_DSTBLEND_ONE:
dstFactor = nvrhi::BlendFactor::One;
break;
case GLS_DSTBLEND_SRC_COLOR:
dstFactor = nvrhi::BlendFactor::SrcColor;
break;
case GLS_DSTBLEND_ONE_MINUS_SRC_COLOR:
dstFactor = nvrhi::BlendFactor::OneMinusSrcColor;
break;
case GLS_DSTBLEND_SRC_ALPHA:
dstFactor = nvrhi::BlendFactor::SrcAlpha;
break;
case GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA:
dstFactor = nvrhi::BlendFactor::OneMinusSrcAlpha;
break;
case GLS_DSTBLEND_DST_ALPHA:
dstFactor = nvrhi::BlendFactor::DstAlpha;
break;
case GLS_DSTBLEND_ONE_MINUS_DST_ALPHA:
dstFactor = nvrhi::BlendFactor::OneMinusDstAlpha;
break;
default:
assert( !"GL_State: invalid dst blend state bits\n" );
break;
}
// Only actually update GL's blend func if blending is enabled.
if( srcFactor == nvrhi::BlendFactor::One && dstFactor == nvrhi::BlendFactor::Zero )
{
renderTarget.disableBlend();
}
else
{
currentBlendState.setAlphaToCoverageEnable( true );
renderTarget.enableBlend();
renderTarget.setSrcBlend( srcFactor );
renderTarget.setDestBlend( dstFactor );
}
}
//
// check depthmask
//
if( diff & GLS_DEPTHMASK )
{
if( stateBits & GLS_DEPTHMASK )
{
currentDepthStencilState.disableDepthWrite();
if( ( stateBits & GLS_DEPTHFUNC_BITS ) == GLS_DEPTHFUNC_ALWAYS )
{
currentDepthStencilState.disableDepthTest();
}
}
}
//
// check colormask
//
if( diff & ( GLS_REDMASK | GLS_GREENMASK | GLS_BLUEMASK | GLS_ALPHAMASK ) )
{
nvrhi::ColorMask mask{ nvrhi::ColorMask::All };
if( stateBits & GLS_REDMASK )
{
mask = mask & ~nvrhi::ColorMask::Red;
}
if( stateBits & GLS_GREENMASK )
{
mask = mask & ~nvrhi::ColorMask::Green;
}
if( stateBits & GLS_BLUEMASK )
{
mask = mask & ~nvrhi::ColorMask::Blue;
}
if( stateBits & GLS_ALPHAMASK )
{
mask = mask & ~nvrhi::ColorMask::Alpha;
}
renderTarget.setBlendEnable( true );
renderTarget.setColorWriteMask( mask );
}
currentBlendState.setRenderTarget( 0, renderTarget );
//
// fill/line mode
//
if( diff & GLS_POLYMODE_LINE )
{
if( stateBits & GLS_POLYMODE_LINE )
{
currentRasterState.setFillMode( nvrhi::RasterFillMode::Line );
currentRasterState.setCullNone();
}
else
{
currentRasterState.setCullNone();
currentRasterState.setFillMode( nvrhi::RasterFillMode::Fill );
}
}
//
// polygon offset
//
if( diff & GLS_POLYGON_OFFSET )
{
if( stateBits & GLS_POLYGON_OFFSET )
{
currentRasterState.enableQuadFill();
}
else
{
currentRasterState.disableQuadFill();
}
}
nvrhi::DepthStencilState::StencilOpDesc stencilOp;
//
// stencil
//
if( diff & ( GLS_STENCIL_FUNC_BITS | GLS_STENCIL_OP_BITS ) )
{
if( ( stateBits & ( GLS_STENCIL_FUNC_BITS | GLS_STENCIL_OP_BITS ) ) != 0 )
{
currentDepthStencilState.enableStencil();
//currentDepthStencilState.enableDepthWrite();
}
else
{
currentDepthStencilState.disableStencil();
//currentDepthStencilState.disableDepthWrite();
}
}
if( diff & ( GLS_STENCIL_FUNC_BITS | GLS_STENCIL_FUNC_REF_BITS | GLS_STENCIL_FUNC_MASK_BITS ) )
{
GLuint ref = GLuint( ( stateBits & GLS_STENCIL_FUNC_REF_BITS ) >> GLS_STENCIL_FUNC_REF_SHIFT );
GLuint mask = GLuint( ( stateBits & GLS_STENCIL_FUNC_MASK_BITS ) >> GLS_STENCIL_FUNC_MASK_SHIFT );
GLenum func = 0;
currentDepthStencilState.setStencilRefValue( ( stateBits & GLS_STENCIL_FUNC_REF_BITS ) >> GLS_STENCIL_FUNC_REF_SHIFT );
currentDepthStencilState.setStencilReadMask( ( stateBits & GLS_STENCIL_FUNC_MASK_BITS ) >> GLS_STENCIL_FUNC_MASK_SHIFT );
currentDepthStencilState.setStencilWriteMask( ( stateBits & GLS_STENCIL_FUNC_MASK_BITS ) >> GLS_STENCIL_FUNC_MASK_SHIFT );
switch( stateBits & GLS_STENCIL_FUNC_BITS )
{
case GLS_STENCIL_FUNC_NEVER:
stencilOp.setStencilFunc( nvrhi::ComparisonFunc::Never );
break;
case GLS_STENCIL_FUNC_LESS:
stencilOp.setStencilFunc( nvrhi::ComparisonFunc::Less );
break;
case GLS_STENCIL_FUNC_EQUAL:
stencilOp.setStencilFunc( nvrhi::ComparisonFunc::Equal );
break;
case GLS_STENCIL_FUNC_LEQUAL:
stencilOp.setStencilFunc( nvrhi::ComparisonFunc::LessOrEqual );
break;
case GLS_STENCIL_FUNC_GREATER:
stencilOp.setStencilFunc( nvrhi::ComparisonFunc::Greater );
break;
case GLS_STENCIL_FUNC_NOTEQUAL:
stencilOp.setStencilFunc( nvrhi::ComparisonFunc::NotEqual );
break;
case GLS_STENCIL_FUNC_GEQUAL:
stencilOp.setStencilFunc( nvrhi::ComparisonFunc::GreaterOrEqual );
break;
case GLS_STENCIL_FUNC_ALWAYS:
stencilOp.setStencilFunc( nvrhi::ComparisonFunc::Always );
break;
}
}
if( diff & ( GLS_STENCIL_OP_FAIL_BITS | GLS_STENCIL_OP_ZFAIL_BITS | GLS_STENCIL_OP_PASS_BITS ) )
{
GLenum sFail = 0;
GLenum zFail = 0;
GLenum pass = 0;
switch( stateBits & GLS_STENCIL_OP_FAIL_BITS )
{
case GLS_STENCIL_OP_FAIL_KEEP:
stencilOp.setFailOp( nvrhi::StencilOp::Keep );
break;
case GLS_STENCIL_OP_FAIL_ZERO:
stencilOp.setFailOp( nvrhi::StencilOp::Zero );
break;
case GLS_STENCIL_OP_FAIL_REPLACE:
stencilOp.setFailOp( nvrhi::StencilOp::Replace );
break;
case GLS_STENCIL_OP_FAIL_INCR:
stencilOp.setFailOp( nvrhi::StencilOp::IncrementAndClamp );
break;
case GLS_STENCIL_OP_FAIL_DECR:
stencilOp.setFailOp( nvrhi::StencilOp::DecrementAndClamp );
break;
case GLS_STENCIL_OP_FAIL_INVERT:
stencilOp.setFailOp( nvrhi::StencilOp::Invert );
break;
case GLS_STENCIL_OP_FAIL_INCR_WRAP:
stencilOp.setFailOp( nvrhi::StencilOp::IncrementAndWrap );
break;
case GLS_STENCIL_OP_FAIL_DECR_WRAP:
stencilOp.setFailOp( nvrhi::StencilOp::DecrementAndWrap );
break;
}
switch( stateBits & GLS_STENCIL_OP_ZFAIL_BITS )
{
case GLS_STENCIL_OP_ZFAIL_KEEP:
stencilOp.setDepthFailOp( nvrhi::StencilOp::Keep );
break;
case GLS_STENCIL_OP_ZFAIL_ZERO:
stencilOp.setDepthFailOp( nvrhi::StencilOp::Zero );
break;
case GLS_STENCIL_OP_ZFAIL_REPLACE:
stencilOp.setDepthFailOp( nvrhi::StencilOp::Replace );
break;
case GLS_STENCIL_OP_ZFAIL_INCR:
stencilOp.setDepthFailOp( nvrhi::StencilOp::IncrementAndClamp );
break;
case GLS_STENCIL_OP_ZFAIL_DECR:
stencilOp.setDepthFailOp( nvrhi::StencilOp::DecrementAndClamp );
break;
case GLS_STENCIL_OP_ZFAIL_INVERT:
stencilOp.setDepthFailOp( nvrhi::StencilOp::Invert );
break;
case GLS_STENCIL_OP_ZFAIL_INCR_WRAP:
stencilOp.setDepthFailOp( nvrhi::StencilOp::IncrementAndWrap );
break;
case GLS_STENCIL_OP_ZFAIL_DECR_WRAP:
stencilOp.setDepthFailOp( nvrhi::StencilOp::DecrementAndWrap );
break;
}
switch( stateBits & GLS_STENCIL_OP_PASS_BITS )
{
case GLS_STENCIL_OP_PASS_KEEP:
stencilOp.setPassOp( nvrhi::StencilOp::Keep );
break;
case GLS_STENCIL_OP_PASS_ZERO:
stencilOp.setPassOp( nvrhi::StencilOp::Zero );
break;
case GLS_STENCIL_OP_PASS_REPLACE:
stencilOp.setPassOp( nvrhi::StencilOp::Replace );
break;
case GLS_STENCIL_OP_PASS_INCR:
stencilOp.setPassOp( nvrhi::StencilOp::IncrementAndClamp );
break;
case GLS_STENCIL_OP_PASS_DECR:
stencilOp.setPassOp( nvrhi::StencilOp::DecrementAndClamp );
break;
case GLS_STENCIL_OP_PASS_INVERT:
stencilOp.setPassOp( nvrhi::StencilOp::Invert );
break;
case GLS_STENCIL_OP_PASS_INCR_WRAP:
stencilOp.setPassOp( nvrhi::StencilOp::IncrementAndWrap );
break;
case GLS_STENCIL_OP_PASS_DECR_WRAP:
stencilOp.setPassOp( nvrhi::StencilOp::DecrementAndWrap );
break;
}
}
currentDepthStencilState.setFrontFaceStencil( stencilOp );
glStateBits = stateBits;
// the rest of this is handled by PipelineCache::GetOrCreatePipeline and GetRenderState similar to Vulkan
}
/*

View file

@ -1,11 +1,38 @@
#include <precompiled.h>
#pragma hdrstrop
/*
===========================================================================
Doom 3 BFG Edition GPL Source Code
Copyright (C) 2022 Stephen Pridham
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#include "precompiled.h"
#pragma hdrstop
#include "renderer/RenderCommon.h"
#include "PipelineCache.h"
void GetRenderState( uint64 stateBits, PipelineKey key, nvrhi::RenderState& renderState );
PipelineCache::PipelineCache()
{
@ -52,8 +79,8 @@ nvrhi::GraphicsPipelineHandle PipelineCache::GetOrCreatePipeline( const Pipeline
target.enableBlend();
}
//pipelineDesc.renderState.rasterState.enableDepthClip();
pipelineDesc.renderState.rasterState.depthBias = 0;
pipelineDesc.renderState.rasterState.slopeScaledDepthBias = 0;
//pipelineDesc.renderState.rasterState.depthBias = 0;
//pipelineDesc.renderState.rasterState.slopeScaledDepthBias = 0;
// Specialize the state with the state key.
GetRenderState( key.state, key, pipelineDesc.renderState );
@ -66,76 +93,86 @@ nvrhi::GraphicsPipelineHandle PipelineCache::GetOrCreatePipeline( const Pipeline
}
void GetRenderState( uint64 stateBits, PipelineKey key, nvrhi::RenderState& renderState )
void PipelineCache::GetRenderState( uint64 stateBits, PipelineKey key, nvrhi::RenderState& renderState )
{
/*
uint64 diff = stateBits ^ GLS_DEFAULT;
if( diff == 0 )
{
return;
}
*/
auto& currentBlendState = renderState.blendState;
auto& currentDepthStencilState = renderState.depthStencilState;
auto& currentRasterState = renderState.rasterState;
auto& rasterizationState = renderState.rasterState;
//
// culling
// culling & mirrors
//
if( diff & ( GLS_CULL_BITS ) )//| GLS_MIRROR_VIEW ) )
//if( stateBits & ( GLS_CULL_BITS ) )//| GLS_MIRROR_VIEW ) )
{
switch( stateBits & GLS_CULL_BITS )
{
case GLS_CULL_TWOSIDED:
currentRasterState.setCullNone();
rasterizationState.setCullNone();
break;
case GLS_CULL_BACKSIDED:
if( key.mirrored )
if( stateBits & GLS_MIRROR_VIEW )
{
stateBits |= GLS_MIRROR_VIEW;
currentRasterState.setCullFront();
rasterizationState.setCullFront();
}
else
{
currentRasterState.setCullBack();
rasterizationState.setCullBack();
}
break;
case GLS_CULL_FRONTSIDED:
default:
if( key.mirrored )
if( stateBits & GLS_MIRROR_VIEW )
{
stateBits |= GLS_MIRROR_VIEW;
currentRasterState.setCullBack();
rasterizationState.setCullBack();
}
else
{
currentRasterState.setCullFront();
rasterizationState.setCullFront();
}
break;
}
}
rasterizationState.setFrontCounterClockwise( ( stateBits & GLS_CLOCKWISE ) == 0 );
//
// check depthFunc bits
// fill/line mode
//
if( diff & GLS_DEPTHFUNC_BITS )
//if( diff & GLS_POLYMODE_LINE )
{
switch( stateBits & GLS_DEPTHFUNC_BITS )
if( stateBits & GLS_POLYMODE_LINE )
{
case GLS_DEPTHFUNC_EQUAL:
currentDepthStencilState.depthFunc = nvrhi::ComparisonFunc::Equal;
break;
case GLS_DEPTHFUNC_ALWAYS:
currentDepthStencilState.depthFunc = nvrhi::ComparisonFunc::Always;
break;
case GLS_DEPTHFUNC_LESS:
currentDepthStencilState.depthFunc = nvrhi::ComparisonFunc::Less;
break;
case GLS_DEPTHFUNC_GREATER:
currentDepthStencilState.depthFunc = nvrhi::ComparisonFunc::Greater;
break;
rasterizationState.setFillMode( nvrhi::RasterFillMode::Wireframe );
}
else
{
rasterizationState.setFillMode( nvrhi::RasterFillMode::Solid );
}
}
//
// polygon offset
//
//if( diff & GLS_POLYGON_OFFSET )
{
if( stateBits & GLS_POLYGON_OFFSET )
{
rasterizationState.depthBias = key.depthBias;
rasterizationState.slopeScaledDepthBias = key.slopeBias;
rasterizationState.enableQuadFill();
}
else
{
//currentRasterState.disableQuadFill();
}
}
@ -144,11 +181,9 @@ void GetRenderState( uint64 stateBits, PipelineKey key, nvrhi::RenderState& rend
//
// check blend bits
//
if( diff & ( GLS_SRCBLEND_BITS | GLS_DSTBLEND_BITS ) )
//if( stateBits & ( GLS_SRCBLEND_BITS | GLS_DSTBLEND_BITS ) )
{
nvrhi::BlendFactor srcFactor = nvrhi::BlendFactor::One;
nvrhi::BlendFactor dstFactor = nvrhi::BlendFactor::One;
switch( stateBits & GLS_SRCBLEND_BITS )
{
case GLS_SRCBLEND_ZERO:
@ -180,6 +215,7 @@ void GetRenderState( uint64 stateBits, PipelineKey key, nvrhi::RenderState& rend
break;
}
nvrhi::BlendFactor dstFactor = nvrhi::BlendFactor::Zero;
switch( stateBits & GLS_DSTBLEND_BITS )
{
case GLS_DSTBLEND_ZERO:
@ -211,6 +247,24 @@ void GetRenderState( uint64 stateBits, PipelineKey key, nvrhi::RenderState& rend
break;
}
// RB: blend ops are only used by the SWF render states so far
nvrhi::BlendOp blendOp = nvrhi::BlendOp::Add;
switch( stateBits & GLS_BLENDOP_BITS )
{
case GLS_BLENDOP_MIN:
blendOp = nvrhi::BlendOp::Min;
break;
case GLS_BLENDOP_MAX:
blendOp = nvrhi::BlendOp::Max;
break;
case GLS_BLENDOP_ADD:
blendOp = nvrhi::BlendOp::Add;
break;
case GLS_BLENDOP_SUB:
blendOp = nvrhi::BlendOp::Subrtact;
break;
}
// Only actually update GL's blend func if blending is enabled.
if( srcFactor == nvrhi::BlendFactor::One && dstFactor == nvrhi::BlendFactor::Zero )
{
@ -218,32 +272,23 @@ void GetRenderState( uint64 stateBits, PipelineKey key, nvrhi::RenderState& rend
}
else
{
currentBlendState.setAlphaToCoverageEnable( true );
//colorBlendState.setAlphaToCoverageEnable( true );
renderTarget.enableBlend();
//renderTarget.setBlendOp( blendOp );
renderTarget.setSrcBlend( srcFactor );
renderTarget.setDestBlend( dstFactor );
}
}
//
// check depthmask
//
if( diff & GLS_DEPTHMASK )
{
if( stateBits & GLS_DEPTHMASK )
{
currentDepthStencilState.disableDepthWrite();
if( ( stateBits & GLS_DEPTHFUNC_BITS ) == GLS_DEPTHFUNC_ALWAYS )
{
currentDepthStencilState.disableDepthTest();
}
//renderTarget.setBlendOpAlpha( blendOp );
//renderTarget.setSrcBlendAlpha( srcFactor );
//renderTarget.setDestBlendAlpha( dstFactor );
}
}
//
// check colormask
//
if( diff & ( GLS_REDMASK | GLS_GREENMASK | GLS_BLUEMASK | GLS_ALPHAMASK ) )
//if( diff & ( GLS_REDMASK | GLS_GREENMASK | GLS_BLUEMASK | GLS_ALPHAMASK ) )
{
nvrhi::ColorMask mask{ nvrhi::ColorMask::All };
@ -268,39 +313,45 @@ void GetRenderState( uint64 stateBits, PipelineKey key, nvrhi::RenderState& rend
renderTarget.setColorWriteMask( mask );
}
currentBlendState.setRenderTarget( 0, renderTarget );
renderState.blendState.setRenderTarget( 0, renderTarget );
auto& depthStencilState = renderState.depthStencilState;
//
// fill/line mode
// check depthFunc bits
//
if( diff & GLS_POLYMODE_LINE )
//if( diff & GLS_DEPTHFUNC_BITS )
{
if( stateBits & GLS_POLYMODE_LINE )
switch( stateBits & GLS_DEPTHFUNC_BITS )
{
currentRasterState.setFillMode( nvrhi::RasterFillMode::Wireframe );
//currentRasterState.setCullNone();
}
else
{
//currentRasterState.setCullNone();
currentRasterState.setFillMode( nvrhi::RasterFillMode::Solid );
case GLS_DEPTHFUNC_EQUAL:
depthStencilState.depthFunc = nvrhi::ComparisonFunc::Equal;
break;
case GLS_DEPTHFUNC_ALWAYS:
depthStencilState.depthFunc = nvrhi::ComparisonFunc::Always;
break;
case GLS_DEPTHFUNC_LESS:
depthStencilState.depthFunc = nvrhi::ComparisonFunc::LessOrEqual;
break;
case GLS_DEPTHFUNC_GREATER:
depthStencilState.depthFunc = nvrhi::ComparisonFunc::Greater;
break;
}
}
//
// polygon offset
// check depthmask
//
if( diff & GLS_POLYGON_OFFSET )
//if( diff & GLS_DEPTHMASK )
{
if( stateBits & GLS_POLYGON_OFFSET )
if( stateBits & GLS_DEPTHMASK )
{
currentRasterState.depthBias = key.depthBias;
currentRasterState.slopeScaledDepthBias = key.slopeBias;
currentRasterState.enableQuadFill();
}
else
{
//currentRasterState.disableQuadFill();
depthStencilState.disableDepthWrite();
if( ( stateBits & GLS_DEPTHFUNC_BITS ) == GLS_DEPTHFUNC_ALWAYS )
{
depthStencilState.disableDepthTest();
}
}
}
@ -309,28 +360,27 @@ void GetRenderState( uint64 stateBits, PipelineKey key, nvrhi::RenderState& rend
//
// stencil
//
if( diff & ( GLS_STENCIL_FUNC_BITS | GLS_STENCIL_OP_BITS ) )
//if( diff & ( GLS_STENCIL_FUNC_BITS | GLS_STENCIL_OP_BITS ) )
{
if( ( stateBits & ( GLS_STENCIL_FUNC_BITS | GLS_STENCIL_OP_BITS ) ) != 0 )
{
currentDepthStencilState.enableStencil();
//currentDepthStencilState.enableDepthWrite();
depthStencilState.enableStencil();
}
else
{
currentDepthStencilState.disableStencil();
//currentDepthStencilState.disableDepthWrite();
depthStencilState.disableStencil();
}
}
if( diff & ( GLS_STENCIL_FUNC_BITS | GLS_STENCIL_FUNC_REF_BITS | GLS_STENCIL_FUNC_MASK_BITS ) )
if( stateBits & ( GLS_STENCIL_FUNC_BITS | GLS_STENCIL_FUNC_REF_BITS | GLS_STENCIL_FUNC_MASK_BITS ) )
{
GLuint ref = GLuint( ( stateBits & GLS_STENCIL_FUNC_REF_BITS ) >> GLS_STENCIL_FUNC_REF_SHIFT );
GLuint mask = GLuint( ( stateBits & GLS_STENCIL_FUNC_MASK_BITS ) >> GLS_STENCIL_FUNC_MASK_SHIFT );
GLenum func = 0;
currentDepthStencilState.setStencilRefValue( ( stateBits & GLS_STENCIL_FUNC_REF_BITS ) >> GLS_STENCIL_FUNC_REF_SHIFT );
currentDepthStencilState.setStencilReadMask( ( stateBits & GLS_STENCIL_FUNC_MASK_BITS ) >> GLS_STENCIL_FUNC_MASK_SHIFT );
currentDepthStencilState.setStencilWriteMask( ( stateBits & GLS_STENCIL_FUNC_MASK_BITS ) >> GLS_STENCIL_FUNC_MASK_SHIFT );
depthStencilState.setStencilRefValue( ( stateBits & GLS_STENCIL_FUNC_REF_BITS ) >> GLS_STENCIL_FUNC_REF_SHIFT );
depthStencilState.setStencilReadMask( ( stateBits & GLS_STENCIL_FUNC_MASK_BITS ) >> GLS_STENCIL_FUNC_MASK_SHIFT );
depthStencilState.setStencilWriteMask( ( stateBits & GLS_STENCIL_FUNC_MASK_BITS ) >> GLS_STENCIL_FUNC_MASK_SHIFT );
switch( stateBits & GLS_STENCIL_FUNC_BITS )
{
@ -360,7 +410,8 @@ void GetRenderState( uint64 stateBits, PipelineKey key, nvrhi::RenderState& rend
break;
}
}
if( diff & ( GLS_STENCIL_OP_FAIL_BITS | GLS_STENCIL_OP_ZFAIL_BITS | GLS_STENCIL_OP_PASS_BITS ) )
if( stateBits & ( GLS_STENCIL_OP_FAIL_BITS | GLS_STENCIL_OP_ZFAIL_BITS | GLS_STENCIL_OP_PASS_BITS ) )
{
GLenum sFail = 0;
GLenum zFail = 0;
@ -393,6 +444,7 @@ void GetRenderState( uint64 stateBits, PipelineKey key, nvrhi::RenderState& rend
stencilOp.setFailOp( nvrhi::StencilOp::DecrementAndWrap );
break;
}
switch( stateBits & GLS_STENCIL_OP_ZFAIL_BITS )
{
case GLS_STENCIL_OP_ZFAIL_KEEP:
@ -420,6 +472,7 @@ void GetRenderState( uint64 stateBits, PipelineKey key, nvrhi::RenderState& rend
stencilOp.setDepthFailOp( nvrhi::StencilOp::DecrementAndWrap );
break;
}
switch( stateBits & GLS_STENCIL_OP_PASS_BITS )
{
case GLS_STENCIL_OP_PASS_KEEP:
@ -449,5 +502,5 @@ void GetRenderState( uint64 stateBits, PipelineKey key, nvrhi::RenderState& rend
}
}
currentDepthStencilState.setFrontFaceStencil( stencilOp );
depthStencilState.setFrontFaceStencil( stencilOp );
}

View file

@ -1,12 +1,37 @@
/*
===========================================================================
Doom 3 BFG Edition GPL Source Code
Copyright (C) 2022 Stephen Pridham
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#ifndef RENDERER_PIPELINECACHE_H_
#define RENDERER_PIPELINECACHE_H_
struct PipelineKey
{
uint64 state;
int program;
bool mirrored;
int depthBias;
float slopeBias;
@ -17,7 +42,6 @@ inline bool operator==( const PipelineKey& lhs, const PipelineKey& rhs )
{
return lhs.state == rhs.state &&
lhs.program == rhs.program &&
lhs.mirrored == rhs.mirrored &&
lhs.framebuffer == rhs.framebuffer &&
lhs.depthBias == rhs.depthBias &&
lhs.slopeBias == rhs.slopeBias;
@ -31,7 +55,6 @@ struct std::hash<PipelineKey>
std::size_t h = 0;
nvrhi::hash_combine( h, key.state );
nvrhi::hash_combine( h, key.program );
nvrhi::hash_combine( h, key.mirrored );
nvrhi::hash_combine( h, key.framebuffer );
nvrhi::hash_combine( h, key.depthBias );
nvrhi::hash_combine( h, key.slopeBias );
@ -53,6 +76,8 @@ public:
private:
void GetRenderState( uint64 stateBits, PipelineKey key, nvrhi::RenderState& renderState );
nvrhi::DeviceHandle device;
idHashIndex pipelineHash;
idList<std::pair<PipelineKey, nvrhi::GraphicsPipelineHandle>> pipelines;

View file

@ -513,7 +513,7 @@ private:
idStaticList<nvrhi::BindingSetDesc, nvrhi::c_MaxBindingLayouts> pendingBindingSetDescs;
nvrhi::BindingLayoutHandle currentBindingLayout;
nvrhi::GraphicsPipelineHandle currentPipeline;
nvrhi::RenderState currentRenderState;
//nvrhi::RenderState currentRenderState;
Framebuffer* currentFrameBuffer;
Framebuffer* lastFrameBuffer;