1
0
forked from 0ad/0ad

Switches from pipeline state descriptions to pipeline states.

Tested By: phosit, Stan
Differential Revision: https://code.wildfiregames.com/D4850
This was SVN commit r27328.
This commit is contained in:
Vladislav Belov 2022-12-31 18:29:44 +00:00
parent 0152c26b72
commit 4ed41d4a9a
48 changed files with 794 additions and 319 deletions

View File

@ -7,6 +7,7 @@
<pass shader="arb/terrain_blend"> <pass shader="arb/terrain_blend">
<depth mask="false"/> <depth mask="false"/>
<cull mode="FRONT"/> <cull mode="FRONT"/>
<blend src="src_alpha" dst="one_minus_src_alpha"/>
</pass> </pass>
</technique> </technique>
@ -16,15 +17,18 @@
<pass shader="glsl/terrain_blend"> <pass shader="glsl/terrain_blend">
<depth mask="false"/> <depth mask="false"/>
<cull mode="FRONT"/> <cull mode="FRONT"/>
<blend src="src_alpha" dst="one_minus_src_alpha"/>
</pass> </pass>
</technique> </technique>
<technique> <technique>
<require shaders="arb"/> <require shaders="arb"/>
<require context="MODE_WIREFRAME"/> <require context="MODE_WIREFRAME"/>
<pass shader="arb/terrain_blend"> <pass shader="arb/terrain_blend">
<depth mask="false"/> <depth mask="false"/>
<polygon mode="LINE"/> <polygon mode="LINE"/>
<blend src="src_alpha" dst="one_minus_src_alpha"/>
</pass> </pass>
</technique> </technique>
@ -34,6 +38,7 @@
<pass shader="glsl/terrain_blend"> <pass shader="glsl/terrain_blend">
<depth mask="false"/> <depth mask="false"/>
<polygon mode="LINE"/> <polygon mode="LINE"/>
<blend src="src_alpha" dst="one_minus_src_alpha"/>
</pass> </pass>
</technique> </technique>
@ -42,6 +47,7 @@
<require shaders="arb"/> <require shaders="arb"/>
<pass shader="arb/terrain_blend"> <pass shader="arb/terrain_blend">
<depth mask="false"/> <depth mask="false"/>
<blend src="src_alpha" dst="one_minus_src_alpha"/>
</pass> </pass>
</technique> </technique>
@ -49,6 +55,7 @@
<require shaders="glsl"/> <require shaders="glsl"/>
<pass shader="glsl/terrain_blend"> <pass shader="glsl/terrain_blend">
<depth mask="false"/> <depth mask="false"/>
<blend src="src_alpha" dst="one_minus_src_alpha"/>
</pass> </pass>
</technique> </technique>

View File

@ -7,6 +7,7 @@
<pass shader="arb/terrain_decal"> <pass shader="arb/terrain_decal">
<depth mask="false"/> <depth mask="false"/>
<cull mode="FRONT"/> <cull mode="FRONT"/>
<blend src="src_alpha" dst="one_minus_src_alpha"/>
</pass> </pass>
</technique> </technique>
@ -16,6 +17,7 @@
<pass shader="glsl/terrain_decal"> <pass shader="glsl/terrain_decal">
<depth mask="false"/> <depth mask="false"/>
<cull mode="FRONT"/> <cull mode="FRONT"/>
<blend src="src_alpha" dst="one_minus_src_alpha"/>
</pass> </pass>
</technique> </technique>
@ -26,6 +28,7 @@
<pass shader="arb/terrain_decal"> <pass shader="arb/terrain_decal">
<depth mask="false"/> <depth mask="false"/>
<polygon mode="LINE"/> <polygon mode="LINE"/>
<blend src="src_alpha" dst="one_minus_src_alpha"/>
</pass> </pass>
</technique> </technique>
@ -35,6 +38,7 @@
<pass shader="glsl/terrain_decal"> <pass shader="glsl/terrain_decal">
<depth mask="false"/> <depth mask="false"/>
<polygon mode="LINE"/> <polygon mode="LINE"/>
<blend src="src_alpha" dst="one_minus_src_alpha"/>
</pass> </pass>
</technique> </technique>
@ -43,6 +47,7 @@
<require shaders="arb"/> <require shaders="arb"/>
<pass shader="arb/terrain_decal"> <pass shader="arb/terrain_decal">
<depth mask="false"/> <depth mask="false"/>
<blend src="src_alpha" dst="one_minus_src_alpha"/>
</pass> </pass>
</technique> </technique>
@ -50,6 +55,7 @@
<require shaders="glsl"/> <require shaders="glsl"/>
<pass shader="glsl/terrain_decal"> <pass shader="glsl/terrain_decal">
<depth mask="false"/> <depth mask="false"/>
<blend src="src_alpha" dst="one_minus_src_alpha"/>
</pass> </pass>
</technique> </technique>

View File

@ -98,7 +98,7 @@ public:
// The canvas technique must be loaded because we can't render UI without it. // The canvas technique must be loaded because we can't render UI without it.
ENSURE(Tech); ENSURE(Tech);
DeviceCommandContext->SetGraphicsPipelineState( DeviceCommandContext->SetGraphicsPipelineState(
Tech->GetGraphicsPipelineStateDesc()); Tech->GetGraphicsPipelineState());
DeviceCommandContext->BeginPass(); DeviceCommandContext->BeginPass();
Renderer::Backend::IShaderProgram* shader = Tech->GetShader(); Renderer::Backend::IShaderProgram* shader = Tech->GetShader();

View File

@ -146,7 +146,7 @@ void CLOSTexture::InterpolateLOS(Renderer::Backend::IDeviceCommandContext* devic
deviceCommandContext->BeginFramebufferPass(m_SmoothFramebuffers[m_WhichTexture].get()); deviceCommandContext->BeginFramebufferPass(m_SmoothFramebuffers[m_WhichTexture].get());
deviceCommandContext->SetGraphicsPipelineState( deviceCommandContext->SetGraphicsPipelineState(
m_SmoothTech->GetGraphicsPipelineStateDesc()); m_SmoothTech->GetGraphicsPipelineState());
deviceCommandContext->BeginPass(); deviceCommandContext->BeginPass();
Renderer::Backend::IShaderProgram* shader = m_SmoothTech->GetShader(); Renderer::Backend::IShaderProgram* shader = m_SmoothTech->GetShader();

View File

@ -282,6 +282,26 @@ CMiniMapTexture::CMiniMapTexture(CSimulation2& simulation)
m_InstanceVertexArray.Upload(); m_InstanceVertexArray.Upload();
m_InstanceVertexArray.FreeBackingStore(); m_InstanceVertexArray.FreeBackingStore();
} }
CShaderDefines baseDefines;
baseDefines.Add(str_MINIMAP_BASE, str_1);
m_TerritoryTechnique = g_Renderer.GetShaderManager().LoadEffect(
str_minimap, baseDefines,
[](Renderer::Backend::SGraphicsPipelineStateDesc& pipelineStateDesc)
{
pipelineStateDesc.blendState.enabled = true;
pipelineStateDesc.blendState.srcColorBlendFactor = pipelineStateDesc.blendState.srcAlphaBlendFactor =
Renderer::Backend::BlendFactor::SRC_ALPHA;
pipelineStateDesc.blendState.dstColorBlendFactor = pipelineStateDesc.blendState.dstAlphaBlendFactor =
Renderer::Backend::BlendFactor::ONE_MINUS_SRC_ALPHA;
pipelineStateDesc.blendState.colorBlendOp = pipelineStateDesc.blendState.alphaBlendOp =
Renderer::Backend::BlendOp::ADD;
pipelineStateDesc.blendState.colorWriteMask =
Renderer::Backend::ColorWriteMask::RED |
Renderer::Backend::ColorWriteMask::GREEN |
Renderer::Backend::ColorWriteMask::BLUE;
});
} }
CMiniMapTexture::~CMiniMapTexture() CMiniMapTexture::~CMiniMapTexture()
@ -480,7 +500,7 @@ void CMiniMapTexture::RenderFinalTexture(
tech = g_Renderer.GetShaderManager().LoadEffect(str_minimap, baseDefines); tech = g_Renderer.GetShaderManager().LoadEffect(str_minimap, baseDefines);
deviceCommandContext->SetGraphicsPipelineState( deviceCommandContext->SetGraphicsPipelineState(
tech->GetGraphicsPipelineStateDesc()); tech->GetGraphicsPipelineState());
deviceCommandContext->BeginPass(); deviceCommandContext->BeginPass();
shader = tech->GetShader(); shader = tech->GetShader();
@ -513,20 +533,9 @@ void CMiniMapTexture::RenderFinalTexture(
DrawTexture(deviceCommandContext); DrawTexture(deviceCommandContext);
deviceCommandContext->EndPass(); deviceCommandContext->EndPass();
Renderer::Backend::GraphicsPipelineStateDesc pipelineStateDesc = deviceCommandContext->SetGraphicsPipelineState(
tech->GetGraphicsPipelineStateDesc(); m_TerritoryTechnique->GetGraphicsPipelineState());
pipelineStateDesc.blendState.enabled = true; shader = m_TerritoryTechnique->GetShader();
pipelineStateDesc.blendState.srcColorBlendFactor = pipelineStateDesc.blendState.srcAlphaBlendFactor =
Renderer::Backend::BlendFactor::SRC_ALPHA;
pipelineStateDesc.blendState.dstColorBlendFactor = pipelineStateDesc.blendState.dstAlphaBlendFactor =
Renderer::Backend::BlendFactor::ONE_MINUS_SRC_ALPHA;
pipelineStateDesc.blendState.colorBlendOp = pipelineStateDesc.blendState.alphaBlendOp =
Renderer::Backend::BlendOp::ADD;
pipelineStateDesc.blendState.colorWriteMask =
Renderer::Backend::ColorWriteMask::RED |
Renderer::Backend::ColorWriteMask::GREEN |
Renderer::Backend::ColorWriteMask::BLUE;
deviceCommandContext->SetGraphicsPipelineState(pipelineStateDesc);
deviceCommandContext->BeginPass(); deviceCommandContext->BeginPass();
// Draw territory boundaries // Draw territory boundaries
@ -548,7 +557,7 @@ void CMiniMapTexture::RenderFinalTexture(
tech = g_Renderer.GetShaderManager().LoadEffect(str_minimap_los, CShaderDefines()); tech = g_Renderer.GetShaderManager().LoadEffect(str_minimap_los, CShaderDefines());
deviceCommandContext->SetGraphicsPipelineState( deviceCommandContext->SetGraphicsPipelineState(
tech->GetGraphicsPipelineStateDesc()); tech->GetGraphicsPipelineState());
deviceCommandContext->BeginPass(); deviceCommandContext->BeginPass();
shader = tech->GetShader(); shader = tech->GetShader();
@ -765,7 +774,7 @@ void CMiniMapTexture::DrawEntities(
pointDefines.Add(str_USE_GPU_INSTANCING, str_1); pointDefines.Add(str_USE_GPU_INSTANCING, str_1);
CShaderTechniquePtr tech = g_Renderer.GetShaderManager().LoadEffect(str_minimap, pointDefines); CShaderTechniquePtr tech = g_Renderer.GetShaderManager().LoadEffect(str_minimap, pointDefines);
deviceCommandContext->SetGraphicsPipelineState( deviceCommandContext->SetGraphicsPipelineState(
tech->GetGraphicsPipelineStateDesc()); tech->GetGraphicsPipelineState());
deviceCommandContext->BeginPass(); deviceCommandContext->BeginPass();
Renderer::Backend::IShaderProgram* shader = tech->GetShader(); Renderer::Backend::IShaderProgram* shader = tech->GetShader();

View File

@ -19,6 +19,7 @@
#define INCLUDED_MINIMAPTEXTURE #define INCLUDED_MINIMAPTEXTURE
#include "graphics/Color.h" #include "graphics/Color.h"
#include "graphics/ShaderTechniquePtr.h"
#include "graphics/Texture.h" #include "graphics/Texture.h"
#include "maths/Vector2D.h" #include "maths/Vector2D.h"
#include "renderer/backend/IDeviceCommandContext.h" #include "renderer/backend/IDeviceCommandContext.h"
@ -123,6 +124,8 @@ private:
VertexArray m_InstanceVertexArray; VertexArray m_InstanceVertexArray;
VertexArray::Attribute m_InstanceAttributePosition; VertexArray::Attribute m_InstanceAttributePosition;
CShaderTechniquePtr m_TerritoryTechnique;
size_t m_EntitiesDrawn = 0; size_t m_EntitiesDrawn = 0;
double m_PingDuration = 25.0; double m_PingDuration = 25.0;

View File

@ -116,7 +116,8 @@ CShaderTechniquePtr CShaderManager::LoadEffect(CStrIntern name, const CShaderDef
// First time we've seen this key, so construct a new effect: // First time we've seen this key, so construct a new effect:
const VfsPath xmlFilename = L"shaders/effects/" + wstring_from_utf8(name.string()) + L".xml"; const VfsPath xmlFilename = L"shaders/effects/" + wstring_from_utf8(name.string()) + L".xml";
CShaderTechniquePtr tech(new CShaderTechnique(xmlFilename, defines)); CShaderTechniquePtr tech = std::make_shared<CShaderTechnique>(
xmlFilename, defines, PipelineStateDescCallback{});
if (!LoadTechnique(tech)) if (!LoadTechnique(tech))
{ {
LOGERROR("Failed to load effect '%s'", name.c_str()); LOGERROR("Failed to load effect '%s'", name.c_str());
@ -127,6 +128,20 @@ CShaderTechniquePtr CShaderManager::LoadEffect(CStrIntern name, const CShaderDef
return tech; return tech;
} }
CShaderTechniquePtr CShaderManager::LoadEffect(
CStrIntern name, const CShaderDefines& defines, const PipelineStateDescCallback& callback)
{
// We don't cache techniques with callbacks.
const VfsPath xmlFilename = L"shaders/effects/" + wstring_from_utf8(name.string()) + L".xml";
CShaderTechniquePtr technique = std::make_shared<CShaderTechnique>(xmlFilename, defines, callback);
if (!LoadTechnique(technique))
{
LOGERROR("Failed to load effect '%s'", name.c_str());
return {};
}
return technique;
}
bool CShaderManager::LoadTechnique(CShaderTechniquePtr& tech) bool CShaderManager::LoadTechnique(CShaderTechniquePtr& tech)
{ {
PROFILE2("loading technique"); PROFILE2("loading technique");
@ -144,9 +159,14 @@ bool CShaderManager::LoadTechnique(CShaderTechniquePtr& tech)
// By default we assume that we have techinques for every dummy shader. // By default we assume that we have techinques for every dummy shader.
if (device->GetBackend() == Renderer::Backend::Backend::DUMMY) if (device->GetBackend() == Renderer::Backend::Backend::DUMMY)
{ {
const Renderer::Backend::GraphicsPipelineStateDesc passPipelineStateDesc = CShaderProgramPtr shaderProgram = LoadProgram("dummy", tech->GetShaderDefines());
std::vector<CShaderPass> techPasses;
Renderer::Backend::SGraphicsPipelineStateDesc passPipelineStateDesc =
Renderer::Backend::MakeDefaultGraphicsPipelineStateDesc(); Renderer::Backend::MakeDefaultGraphicsPipelineStateDesc();
tech->SetPasses({{passPipelineStateDesc, LoadProgram("dummy", tech->GetShaderDefines())}}); passPipelineStateDesc.shaderProgram = shaderProgram->GetBackendShaderProgram();
techPasses.emplace_back(
device->CreateGraphicsPipelineState(passPipelineStateDesc), shaderProgram);
tech->SetPasses(std::move(techPasses));
return true; return true;
} }
@ -267,7 +287,7 @@ bool CShaderManager::LoadTechnique(CShaderTechniquePtr& tech)
{ {
CShaderDefines passDefines = techDefines; CShaderDefines passDefines = techDefines;
Renderer::Backend::GraphicsPipelineStateDesc passPipelineStateDesc = Renderer::Backend::SGraphicsPipelineStateDesc passPipelineStateDesc =
Renderer::Backend::MakeDefaultGraphicsPipelineStateDesc(); Renderer::Backend::MakeDefaultGraphicsPipelineStateDesc();
XERO_ITER_EL(Child, Element) XERO_ITER_EL(Child, Element)
@ -410,7 +430,11 @@ bool CShaderManager::LoadTechnique(CShaderTechniquePtr& tech)
{ {
for (const VfsPath& shaderProgramPath : shaderProgram->GetFileDependencies()) for (const VfsPath& shaderProgramPath : shaderProgram->GetFileDependencies())
AddTechniqueFileDependency(tech, shaderProgramPath); AddTechniqueFileDependency(tech, shaderProgramPath);
techPasses.emplace_back(passPipelineStateDesc, shaderProgram); if (tech->GetPipelineStateDescCallback())
tech->GetPipelineStateDescCallback()(passPipelineStateDesc);
passPipelineStateDesc.shaderProgram = shaderProgram->GetBackendShaderProgram();
techPasses.emplace_back(
device->CreateGraphicsPipelineState(passPipelineStateDesc), shaderProgram);
} }
} }
} }

View File

@ -21,7 +21,9 @@
#include "graphics/ShaderDefines.h" #include "graphics/ShaderDefines.h"
#include "graphics/ShaderProgram.h" #include "graphics/ShaderProgram.h"
#include "graphics/ShaderTechnique.h" #include "graphics/ShaderTechnique.h"
#include "renderer/backend/PipelineState.h"
#include <functional>
#include <memory> #include <memory>
#include <set> #include <set>
#include <unordered_map> #include <unordered_map>
@ -48,10 +50,18 @@ public:
CShaderTechniquePtr LoadEffect(CStrIntern name, const CShaderDefines& defines); CShaderTechniquePtr LoadEffect(CStrIntern name, const CShaderDefines& defines);
/** /**
* Load a shader effect, with default system defines (from CRenderer::GetSystemShaderDefines). * Load a shader effect, with empty defines.
*/ */
CShaderTechniquePtr LoadEffect(CStrIntern name); CShaderTechniquePtr LoadEffect(CStrIntern name);
/**
* Load a shader effect with the pipeline state description overwriting.
* TODO: we should set all needed states in XML.
*/
using PipelineStateDescCallback = CShaderTechnique::PipelineStateDescCallback;
CShaderTechniquePtr LoadEffect(
CStrIntern name, const CShaderDefines& defines, const PipelineStateDescCallback& callback);
/** /**
* Returns the number of shader effects that are currently loaded. * Returns the number of shader effects that are currently loaded.
*/ */
@ -71,7 +81,7 @@ private:
} }
}; };
// A CShaderProgram contains expensive GL state, so we ought to cache it. // A CShaderProgram contains expensive backend state, so we ought to cache it.
// The compiled state depends solely on the filename and list of defines, // The compiled state depends solely on the filename and list of defines,
// so we store that in CacheKey. // so we store that in CacheKey.
// TODO: is this cache useful when we already have an effect cache? // TODO: is this cache useful when we already have an effect cache?

View File

@ -20,17 +20,20 @@
#include "ShaderTechnique.h" #include "ShaderTechnique.h"
#include "graphics/ShaderProgram.h" #include "graphics/ShaderProgram.h"
#include "renderer/backend/IDevice.h"
CShaderPass::CShaderPass( CShaderPass::CShaderPass(
const Renderer::Backend::GraphicsPipelineStateDesc& pipelineStateDesc, std::unique_ptr<Renderer::Backend::IGraphicsPipelineState> pipelineState,
const CShaderProgramPtr& shader) const CShaderProgramPtr& shader)
: m_PipelineStateDesc(pipelineStateDesc), m_Shader(shader) : m_Shader(shader), m_PipelineState(std::move(pipelineState))
{ {
m_PipelineStateDesc.shaderProgram = m_Shader->GetBackendShaderProgram(); ENSURE(shader);
} }
CShaderTechnique::CShaderTechnique(const VfsPath& path, const CShaderDefines& defines) CShaderTechnique::CShaderTechnique(
: m_Path(path), m_Defines(defines) const VfsPath& path, const CShaderDefines& defines,
const PipelineStateDescCallback& callback)
: m_Path(path), m_Defines(defines), m_PipelineStateDescCallback(callback)
{ {
} }
@ -47,14 +50,14 @@ int CShaderTechnique::GetNumPasses() const
Renderer::Backend::IShaderProgram* CShaderTechnique::GetShader(int pass) const Renderer::Backend::IShaderProgram* CShaderTechnique::GetShader(int pass) const
{ {
ENSURE(0 <= pass && pass < (int)m_Passes.size()); ENSURE(0 <= pass && pass < (int)m_Passes.size());
return m_Passes[pass].GetShader(); return m_Passes[pass].GetPipelineState()->GetShaderProgram();
} }
const Renderer::Backend::GraphicsPipelineStateDesc& Renderer::Backend::IGraphicsPipelineState*
CShaderTechnique::GetGraphicsPipelineStateDesc(int pass) const CShaderTechnique::GetGraphicsPipelineState(int pass) const
{ {
ENSURE(0 <= pass && pass < static_cast<int>(m_Passes.size())); ENSURE(0 <= pass && pass < static_cast<int>(m_Passes.size()));
return m_Passes[pass].GetPipelineStateDesc(); return m_Passes[pass].GetPipelineState();
} }
bool CShaderTechnique::GetSortByDistance() const bool CShaderTechnique::GetSortByDistance() const

View File

@ -21,29 +21,35 @@
#include "graphics/ShaderDefines.h" #include "graphics/ShaderDefines.h"
#include "graphics/ShaderProgram.h" #include "graphics/ShaderProgram.h"
#include "graphics/ShaderTechniquePtr.h" #include "graphics/ShaderTechniquePtr.h"
#include "lib/code_annotation.h"
#include "lib/file/vfs/vfs_path.h" #include "lib/file/vfs/vfs_path.h"
#include "renderer/backend/PipelineState.h" #include "renderer/backend/PipelineState.h"
#include <functional>
#include <memory>
#include <vector> #include <vector>
/** /**
* Implements a render pass consisting of various GL state changes and a shader, * Implements a render pass consisting of a pipeline state and a shader,
* used by CShaderTechnique. * used by CShaderTechnique.
*/ */
class CShaderPass class CShaderPass
{ {
public: public:
CShaderPass(const Renderer::Backend::GraphicsPipelineStateDesc& pipelineStateDesc, const CShaderProgramPtr& shader); CShaderPass(
std::unique_ptr<Renderer::Backend::IGraphicsPipelineState> pipelineState,
const CShaderProgramPtr& shader);
MOVABLE(CShaderPass);
Renderer::Backend::IShaderProgram* GetShader() const { return m_Shader->GetBackendShaderProgram(); } const CShaderProgramPtr& GetShaderProgram() const noexcept { return m_Shader; }
const Renderer::Backend::GraphicsPipelineStateDesc& Renderer::Backend::IGraphicsPipelineState*
GetPipelineStateDesc() const { return m_PipelineStateDesc; } GetPipelineState() const noexcept { return m_PipelineState.get(); }
private: private:
CShaderProgramPtr m_Shader; CShaderProgramPtr m_Shader;
Renderer::Backend::GraphicsPipelineStateDesc m_PipelineStateDesc{}; std::unique_ptr<Renderer::Backend::IGraphicsPipelineState> m_PipelineState;
}; };
/** /**
@ -53,7 +59,10 @@ private:
class CShaderTechnique class CShaderTechnique
{ {
public: public:
CShaderTechnique(const VfsPath& path, const CShaderDefines& defines); using PipelineStateDescCallback =
std::function<void(Renderer::Backend::SGraphicsPipelineStateDesc& pipelineStateDesc)>;
CShaderTechnique(const VfsPath& path, const CShaderDefines& defines, const PipelineStateDescCallback& callback);
void SetPasses(std::vector<CShaderPass>&& passes); void SetPasses(std::vector<CShaderPass>&& passes);
@ -61,8 +70,8 @@ public:
Renderer::Backend::IShaderProgram* GetShader(int pass = 0) const; Renderer::Backend::IShaderProgram* GetShader(int pass = 0) const;
const Renderer::Backend::GraphicsPipelineStateDesc& Renderer::Backend::IGraphicsPipelineState*
GetGraphicsPipelineStateDesc(int pass = 0) const; GetGraphicsPipelineState(int pass = 0) const;
/** /**
* Whether this technique uses alpha blending that requires objects to be * Whether this technique uses alpha blending that requires objects to be
@ -76,6 +85,8 @@ public:
const CShaderDefines& GetShaderDefines() { return m_Defines; } const CShaderDefines& GetShaderDefines() { return m_Defines; }
const PipelineStateDescCallback& GetPipelineStateDescCallback() const { return m_PipelineStateDescCallback; };
private: private:
std::vector<CShaderPass> m_Passes; std::vector<CShaderPass> m_Passes;
@ -84,6 +95,8 @@ private:
// We need additional data to reload the technique. // We need additional data to reload the technique.
VfsPath m_Path; VfsPath m_Path;
CShaderDefines m_Defines; CShaderDefines m_Defines;
PipelineStateDescCallback m_PipelineStateDescCallback;
}; };
#endif // INCLUDED_SHADERTECHNIQUE #endif // INCLUDED_SHADERTECHNIQUE

View File

@ -164,6 +164,9 @@ X(sky_simple)
X(solid) X(solid)
X(sunColor) X(sunColor)
X(sunDir) X(sunDir)
X(terrain_base)
X(terrain_blend)
X(terrain_decal)
X(terrain_solid) X(terrain_solid)
X(tex) X(tex)
X(texSize) X(texSize)

View File

@ -23,6 +23,7 @@
#include "graphics/Color.h" #include "graphics/Color.h"
#include "graphics/ShaderManager.h" #include "graphics/ShaderManager.h"
#include "graphics/ShaderProgram.h" #include "graphics/ShaderProgram.h"
#include "lib/hash.h"
#include "maths/BoundingBoxAligned.h" #include "maths/BoundingBoxAligned.h"
#include "maths/Brush.h" #include "maths/Brush.h"
#include "maths/Matrix3D.h" #include "maths/Matrix3D.h"
@ -34,36 +35,6 @@
#include <cmath> #include <cmath>
namespace
{
void SetGraphicsPipelineStateFromTechAndColor(
Renderer::Backend::IDeviceCommandContext* deviceCommandContext,
const CShaderTechniquePtr& tech, const CColor& color, const bool depthTestEnabled = true,
const bool wireframe = false)
{
Renderer::Backend::GraphicsPipelineStateDesc pipelineStateDesc = tech->GetGraphicsPipelineStateDesc();
pipelineStateDesc.depthStencilState.depthTestEnabled = depthTestEnabled;
if (color.a != 1.0f)
{
pipelineStateDesc.blendState.enabled = true;
pipelineStateDesc.blendState.srcColorBlendFactor = pipelineStateDesc.blendState.srcAlphaBlendFactor =
Renderer::Backend::BlendFactor::SRC_ALPHA;
pipelineStateDesc.blendState.dstColorBlendFactor = pipelineStateDesc.blendState.dstAlphaBlendFactor =
Renderer::Backend::BlendFactor::ONE_MINUS_SRC_ALPHA;
pipelineStateDesc.blendState.colorBlendOp = pipelineStateDesc.blendState.alphaBlendOp =
Renderer::Backend::BlendOp::ADD;
}
else
pipelineStateDesc.blendState.enabled = false;
if (wireframe)
pipelineStateDesc.rasterizationState.polygonMode = Renderer::Backend::PolygonMode::LINE;
pipelineStateDesc.rasterizationState.cullMode = Renderer::Backend::CullMode::NONE;
deviceCommandContext->SetGraphicsPipelineState(pipelineStateDesc);
}
} // anonymous namespace
void CDebugRenderer::DrawLine( void CDebugRenderer::DrawLine(
const CVector3D& from, const CVector3D& to, const CColor& color, const CVector3D& from, const CVector3D& to, const CColor& color,
const float width, const bool depthTestEnabled) const float width, const bool depthTestEnabled)
@ -81,12 +52,13 @@ void CDebugRenderer::DrawLine(
if (line.size() <= 1) if (line.size() <= 1)
return; return;
CShaderTechniquePtr debugLineTech =
g_Renderer.GetShaderManager().LoadEffect(str_debug_line);
Renderer::Backend::IDeviceCommandContext* deviceCommandContext = Renderer::Backend::IDeviceCommandContext* deviceCommandContext =
g_Renderer.GetDeviceCommandContext(); g_Renderer.GetDeviceCommandContext();
SetGraphicsPipelineStateFromTechAndColor(
deviceCommandContext, debugLineTech, color, depthTestEnabled); CShaderTechniquePtr debugLineTech =
GetShaderTechnique(str_debug_line, color, depthTestEnabled);
deviceCommandContext->SetGraphicsPipelineState(
debugLineTech->GetGraphicsPipelineState());
deviceCommandContext->BeginPass(); deviceCommandContext->BeginPass();
const CCamera& viewCamera = g_Renderer.GetSceneRenderer().GetViewCamera(); const CCamera& viewCamera = g_Renderer.GetSceneRenderer().GetViewCamera();
@ -142,11 +114,13 @@ void CDebugRenderer::DrawLine(
void CDebugRenderer::DrawCircle(const CVector3D& origin, const float radius, const CColor& color) void CDebugRenderer::DrawCircle(const CVector3D& origin, const float radius, const CColor& color)
{ {
CShaderTechniquePtr debugCircleTech = CShaderTechniquePtr debugCircleTech =
g_Renderer.GetShaderManager().LoadEffect(str_debug_line); GetShaderTechnique(str_debug_line, color);
Renderer::Backend::IDeviceCommandContext* deviceCommandContext = Renderer::Backend::IDeviceCommandContext* deviceCommandContext =
g_Renderer.GetDeviceCommandContext(); g_Renderer.GetDeviceCommandContext();
SetGraphicsPipelineStateFromTechAndColor(
deviceCommandContext, debugCircleTech, color); deviceCommandContext->SetGraphicsPipelineState(
debugCircleTech->GetGraphicsPipelineState());
deviceCommandContext->BeginPass(); deviceCommandContext->BeginPass();
const CCamera& camera = g_Renderer.GetSceneRenderer().GetViewCamera(); const CCamera& camera = g_Renderer.GetSceneRenderer().GetViewCamera();
@ -208,11 +182,12 @@ void CDebugRenderer::DrawCameraFrustum(const CCamera& camera, const CColor& colo
} }
CShaderTechniquePtr overlayTech = CShaderTechniquePtr overlayTech =
g_Renderer.GetShaderManager().LoadEffect(str_debug_line); GetShaderTechnique(str_debug_line, color, true, wireframe);
Renderer::Backend::IDeviceCommandContext* deviceCommandContext = Renderer::Backend::IDeviceCommandContext* deviceCommandContext =
g_Renderer.GetDeviceCommandContext(); g_Renderer.GetDeviceCommandContext();
SetGraphicsPipelineStateFromTechAndColor( deviceCommandContext->SetGraphicsPipelineState(
deviceCommandContext, overlayTech, color, true, wireframe); overlayTech->GetGraphicsPipelineState());
deviceCommandContext->BeginPass(); deviceCommandContext->BeginPass();
Renderer::Backend::IShaderProgram* overlayShader = overlayTech->GetShader(); Renderer::Backend::IShaderProgram* overlayShader = overlayTech->GetShader();
@ -311,11 +286,13 @@ void CDebugRenderer::DrawBoundingBox(
const CBoundingBoxAligned& boundingBox, const CColor& color, const CBoundingBoxAligned& boundingBox, const CColor& color,
const CMatrix3D& transform, bool wireframe) const CMatrix3D& transform, bool wireframe)
{ {
CShaderTechniquePtr shaderTech = g_Renderer.GetShaderManager().LoadEffect(str_solid); CShaderTechniquePtr shaderTech =
GetShaderTechnique(str_debug_line, color, true, wireframe);
Renderer::Backend::IDeviceCommandContext* deviceCommandContext = Renderer::Backend::IDeviceCommandContext* deviceCommandContext =
g_Renderer.GetDeviceCommandContext(); g_Renderer.GetDeviceCommandContext();
SetGraphicsPipelineStateFromTechAndColor( deviceCommandContext->SetGraphicsPipelineState(
deviceCommandContext, shaderTech, color, true, wireframe); shaderTech->GetGraphicsPipelineState());
deviceCommandContext->BeginPass(); deviceCommandContext->BeginPass();
Renderer::Backend::IShaderProgram* shader = shaderTech->GetShader(); Renderer::Backend::IShaderProgram* shader = shaderTech->GetShader();
@ -360,11 +337,13 @@ void CDebugRenderer::DrawBoundingBox(
void CDebugRenderer::DrawBrush(const CBrush& brush, const CColor& color, bool wireframe) void CDebugRenderer::DrawBrush(const CBrush& brush, const CColor& color, bool wireframe)
{ {
CShaderTechniquePtr shaderTech = g_Renderer.GetShaderManager().LoadEffect(str_solid); CShaderTechniquePtr shaderTech =
GetShaderTechnique(str_debug_line, color, true, wireframe);
Renderer::Backend::IDeviceCommandContext* deviceCommandContext = Renderer::Backend::IDeviceCommandContext* deviceCommandContext =
g_Renderer.GetDeviceCommandContext(); g_Renderer.GetDeviceCommandContext();
SetGraphicsPipelineStateFromTechAndColor( deviceCommandContext->SetGraphicsPipelineState(
deviceCommandContext, shaderTech, color, true, wireframe); shaderTech->GetGraphicsPipelineState());
deviceCommandContext->BeginPass(); deviceCommandContext->BeginPass();
Renderer::Backend::IShaderProgram* shader = shaderTech->GetShader(); Renderer::Backend::IShaderProgram* shader = shaderTech->GetShader();
@ -412,3 +391,56 @@ void CDebugRenderer::DrawBrush(const CBrush& brush, const CColor& color, bool wi
deviceCommandContext->EndPass(); deviceCommandContext->EndPass();
} }
size_t CDebugRenderer::ShaderTechniqueKeyHash::operator()(
const ShaderTechniqueKey& key) const
{
size_t seed = 0;
hash_combine(seed, key.name.GetHash());
hash_combine(seed, key.transparent);
hash_combine(seed, key.depthTestEnabled);
hash_combine(seed, key.wireframe);
return seed;
}
bool CDebugRenderer::ShaderTechniqueKeyEqual::operator()(
const ShaderTechniqueKey& lhs, const ShaderTechniqueKey& rhs) const
{
return
lhs.name == rhs.name && lhs.transparent == rhs.transparent &&
lhs.depthTestEnabled == rhs.depthTestEnabled &&
lhs.wireframe == rhs.wireframe;
}
const CShaderTechniquePtr& CDebugRenderer::GetShaderTechnique(
const CStrIntern name, const CColor& color, const bool depthTestEnabled,
const bool wireframe)
{
const ShaderTechniqueKey key{
name, color.a != 1.0f, depthTestEnabled, wireframe};
CShaderTechniquePtr& shaderTechnique = m_ShaderTechniqueMapping[key];
if (shaderTechnique)
return shaderTechnique;
shaderTechnique = g_Renderer.GetShaderManager().LoadEffect(
name, {},
[key](Renderer::Backend::SGraphicsPipelineStateDesc& pipelineStateDesc)
{
pipelineStateDesc.depthStencilState.depthTestEnabled = key.depthTestEnabled;
if (key.transparent)
{
pipelineStateDesc.blendState.enabled = true;
pipelineStateDesc.blendState.srcColorBlendFactor = pipelineStateDesc.blendState.srcAlphaBlendFactor =
Renderer::Backend::BlendFactor::SRC_ALPHA;
pipelineStateDesc.blendState.dstColorBlendFactor = pipelineStateDesc.blendState.dstAlphaBlendFactor =
Renderer::Backend::BlendFactor::ONE_MINUS_SRC_ALPHA;
pipelineStateDesc.blendState.colorBlendOp = pipelineStateDesc.blendState.alphaBlendOp =
Renderer::Backend::BlendOp::ADD;
}
else
pipelineStateDesc.blendState.enabled = false;
if (key.wireframe)
pipelineStateDesc.rasterizationState.polygonMode = Renderer::Backend::PolygonMode::LINE;
pipelineStateDesc.rasterizationState.cullMode = Renderer::Backend::CullMode::NONE;
});
return shaderTechnique;
}

View File

@ -18,6 +18,10 @@
#ifndef INCLUDED_DEBUGRENDERER #ifndef INCLUDED_DEBUGRENDERER
#define INCLUDED_DEBUGRENDERER #define INCLUDED_DEBUGRENDERER
#include "graphics/ShaderTechniquePtr.h"
#include "ps/CStrIntern.h"
#include <unordered_map>
#include <vector> #include <vector>
class CBoundingBoxAligned; class CBoundingBoxAligned;
@ -64,6 +68,29 @@ public:
* Render the surfaces of the brush as triangles. * Render the surfaces of the brush as triangles.
*/ */
void DrawBrush(const CBrush& brush, const CColor& color, bool wireframe = false); void DrawBrush(const CBrush& brush, const CColor& color, bool wireframe = false);
private:
const CShaderTechniquePtr& GetShaderTechnique(
const CStrIntern name, const CColor& color, const bool depthTestEnabled = true,
const bool wireframe = false);
struct ShaderTechniqueKey
{
CStrIntern name;
bool transparent;
bool depthTestEnabled;
bool wireframe;
};
struct ShaderTechniqueKeyHash
{
size_t operator()(const ShaderTechniqueKey& key) const;
};
struct ShaderTechniqueKeyEqual
{
bool operator()(const ShaderTechniqueKey& lhs, const ShaderTechniqueKey& rhs) const;
};
std::unordered_map<ShaderTechniqueKey, CShaderTechniquePtr, ShaderTechniqueKeyHash, ShaderTechniqueKeyEqual>
m_ShaderTechniqueMapping;
}; };
#endif // INCLUDED_DEBUGRENDERER #endif // INCLUDED_DEBUGRENDERER

View File

@ -152,8 +152,9 @@ void CDecalRData::RenderDecals(
CShaderDefines defines = contextDecal; CShaderDefines defines = contextDecal;
defines.SetMany(itTechBegin->shaderDefines); defines.SetMany(itTechBegin->shaderDefines);
// TODO: move enabling blend to XML.
CShaderTechniquePtr techBase = g_Renderer.GetShaderManager().LoadEffect( CShaderTechniquePtr techBase = g_Renderer.GetShaderManager().LoadEffect(
itTechBegin->shaderEffect, defines); itTechBegin->shaderEffect == str_terrain_base ? str_terrain_decal : itTechBegin->shaderEffect, defines);
if (!techBase) if (!techBase)
{ {
LOGERROR("Terrain renderer failed to load shader effect (%s)\n", LOGERROR("Terrain renderer failed to load shader effect (%s)\n",
@ -164,17 +165,8 @@ void CDecalRData::RenderDecals(
const int numPasses = techBase->GetNumPasses(); const int numPasses = techBase->GetNumPasses();
for (int pass = 0; pass < numPasses; ++pass) for (int pass = 0; pass < numPasses; ++pass)
{ {
Renderer::Backend::GraphicsPipelineStateDesc pipelineStateDesc = deviceCommandContext->SetGraphicsPipelineState(
techBase->GetGraphicsPipelineStateDesc(pass); techBase->GetGraphicsPipelineState(pass));
pipelineStateDesc.blendState.enabled = true;
pipelineStateDesc.blendState.srcColorBlendFactor = pipelineStateDesc.blendState.srcAlphaBlendFactor =
Renderer::Backend::BlendFactor::SRC_ALPHA;
pipelineStateDesc.blendState.dstColorBlendFactor = pipelineStateDesc.blendState.dstAlphaBlendFactor =
Renderer::Backend::BlendFactor::ONE_MINUS_SRC_ALPHA;
pipelineStateDesc.blendState.colorBlendOp = pipelineStateDesc.blendState.alphaBlendOp =
Renderer::Backend::BlendOp::ADD;
pipelineStateDesc.depthStencilState.depthWriteEnabled = false;
deviceCommandContext->SetGraphicsPipelineState(pipelineStateDesc);
deviceCommandContext->BeginPass(); deviceCommandContext->BeginPass();
Renderer::Backend::IShaderProgram* shader = techBase->GetShader(pass); Renderer::Backend::IShaderProgram* shader = techBase->GetShader(pass);

View File

@ -615,7 +615,7 @@ void ShaderModelRenderer::Render(
for (int pass = 0; pass < currentTech->GetNumPasses(); ++pass) for (int pass = 0; pass < currentTech->GetNumPasses(); ++pass)
{ {
deviceCommandContext->SetGraphicsPipelineState( deviceCommandContext->SetGraphicsPipelineState(
currentTech->GetGraphicsPipelineStateDesc(pass)); currentTech->GetGraphicsPipelineState(pass));
deviceCommandContext->BeginPass(); deviceCommandContext->BeginPass();
Renderer::Backend::IShaderProgram* shader = currentTech->GetShader(pass); Renderer::Backend::IShaderProgram* shader = currentTech->GetShader(pass);

View File

@ -31,6 +31,7 @@
#include "ps/CStrInternStatic.h" #include "ps/CStrInternStatic.h"
#include "ps/Game.h" #include "ps/Game.h"
#include "ps/Profile.h" #include "ps/Profile.h"
#include "renderer/backend/PipelineState.h"
#include "renderer/DebugRenderer.h" #include "renderer/DebugRenderer.h"
#include "renderer/Renderer.h" #include "renderer/Renderer.h"
#include "renderer/SceneRenderer.h" #include "renderer/SceneRenderer.h"
@ -47,12 +48,50 @@
namespace namespace
{ {
CShaderTechniquePtr GetOverlayLineShaderTechnique(const CShaderDefines& defines) struct Shader
{ {
return g_Renderer.GetShaderManager().LoadEffect(str_overlay_line, defines); CShaderTechniquePtr technique, techniqueWireframe;
const CShaderTechniquePtr& GetTechnique() const
{
return g_Renderer.GetSceneRenderer().GetOverlayRenderMode() == WIREFRAME
? techniqueWireframe : technique;
}
};
void AdjustOverlayGraphicsPipelineState(Renderer::Backend::SGraphicsPipelineStateDesc& pipelineStateDesc)
{
pipelineStateDesc.depthStencilState.depthWriteEnabled = false;
pipelineStateDesc.blendState.enabled = true;
pipelineStateDesc.blendState.srcColorBlendFactor = pipelineStateDesc.blendState.srcAlphaBlendFactor =
Renderer::Backend::BlendFactor::SRC_ALPHA;
pipelineStateDesc.blendState.dstColorBlendFactor = pipelineStateDesc.blendState.dstAlphaBlendFactor =
Renderer::Backend::BlendFactor::ONE_MINUS_SRC_ALPHA;
pipelineStateDesc.blendState.colorBlendOp = pipelineStateDesc.blendState.alphaBlendOp =
Renderer::Backend::BlendOp::ADD;
} }
} // anonymous namespace Shader CreateShader(
const CStrIntern name, const CShaderDefines& defines)
{
Shader shader;
shader.technique = g_Renderer.GetShaderManager().LoadEffect(
name, defines,
[](Renderer::Backend::SGraphicsPipelineStateDesc& pipelineStateDesc)
{
AdjustOverlayGraphicsPipelineState(pipelineStateDesc);
});
shader.techniqueWireframe = g_Renderer.GetShaderManager().LoadEffect(
name, defines,
[](Renderer::Backend::SGraphicsPipelineStateDesc& pipelineStateDesc)
{
AdjustOverlayGraphicsPipelineState(pipelineStateDesc);
pipelineStateDesc.rasterizationState.polygonMode = Renderer::Backend::PolygonMode::LINE;
});
return shader;
}
/** /**
* Key used to group quads into batches for more efficient rendering. Currently groups by the combination * Key used to group quads into batches for more efficient rendering. Currently groups by the combination
@ -104,12 +143,16 @@ public:
size_t m_NumRenderQuads; size_t m_NumRenderQuads;
}; };
} // anonymous namespace
struct OverlayRendererInternals struct OverlayRendererInternals
{ {
using QuadBatchMap = std::unordered_map<QuadBatchKey, QuadBatchData, QuadBatchHash>; using QuadBatchMap = std::unordered_map<QuadBatchKey, QuadBatchData, QuadBatchHash>;
OverlayRendererInternals(); OverlayRendererInternals();
~OverlayRendererInternals(){ } ~OverlayRendererInternals() = default;
Renderer::Backend::IDevice* device = nullptr;
std::vector<SOverlayLine*> lines; std::vector<SOverlayLine*> lines;
std::vector<SOverlayTexturedLine*> texlines; std::vector<SOverlayTexturedLine*> texlines;
@ -139,6 +182,12 @@ struct OverlayRendererInternals
CShaderDefines defsOverlayLineAlwaysVisible; CShaderDefines defsOverlayLineAlwaysVisible;
CShaderDefines defsQuadOverlay; CShaderDefines defsQuadOverlay;
Shader shaderTexLineNormal;
Shader shaderTexLineAlwaysVisible;
Shader shaderQuadOverlay;
Shader shaderForegroundOverlay;
Shader shaderOverlaySolid;
// Geometry for a unit sphere // Geometry for a unit sphere
std::vector<float> sphereVertexes; std::vector<float> sphereVertexes;
std::vector<u16> sphereIndexes; std::vector<u16> sphereIndexes;
@ -202,6 +251,17 @@ void OverlayRendererInternals::Initialize()
} }
quadIndices.Upload(); quadIndices.Upload();
quadIndices.FreeBackingStore(); quadIndices.FreeBackingStore();
shaderTexLineNormal =
CreateShader(str_overlay_line, defsOverlayLineNormal);
shaderTexLineAlwaysVisible =
CreateShader(str_overlay_line, defsOverlayLineAlwaysVisible);
shaderQuadOverlay =
CreateShader(str_overlay_line, defsQuadOverlay);
shaderForegroundOverlay =
CreateShader(str_foreground_overlay, {});
shaderOverlaySolid =
CreateShader(str_overlay_solid, {});
} }
OverlayRenderer::OverlayRenderer() OverlayRenderer::OverlayRenderer()
@ -407,25 +467,14 @@ void OverlayRenderer::RenderTexturedOverlayLines(Renderer::Backend::IDeviceComma
CLOSTexture& los = g_Renderer.GetSceneRenderer().GetScene().GetLOSTexture(); CLOSTexture& los = g_Renderer.GetSceneRenderer().GetScene().GetLOSTexture();
CShaderTechniquePtr shaderTechTexLineNormal = GetOverlayLineShaderTechnique(m->defsOverlayLineNormal); if (m->shaderTexLineNormal.technique)
if (shaderTechTexLineNormal)
{ {
Renderer::Backend::GraphicsPipelineStateDesc pipelineStateDesc = const CShaderTechniquePtr& shaderTechnique = m->shaderTexLineNormal.GetTechnique();
shaderTechTexLineNormal->GetGraphicsPipelineStateDesc(); deviceCommandContext->SetGraphicsPipelineState(
pipelineStateDesc.depthStencilState.depthWriteEnabled = false; shaderTechnique->GetGraphicsPipelineState());
pipelineStateDesc.blendState.enabled = true;
pipelineStateDesc.blendState.srcColorBlendFactor = pipelineStateDesc.blendState.srcAlphaBlendFactor =
Renderer::Backend::BlendFactor::SRC_ALPHA;
pipelineStateDesc.blendState.dstColorBlendFactor = pipelineStateDesc.blendState.dstAlphaBlendFactor =
Renderer::Backend::BlendFactor::ONE_MINUS_SRC_ALPHA;
pipelineStateDesc.blendState.colorBlendOp = pipelineStateDesc.blendState.alphaBlendOp =
Renderer::Backend::BlendOp::ADD;
if (g_Renderer.GetSceneRenderer().GetOverlayRenderMode() == WIREFRAME)
pipelineStateDesc.rasterizationState.polygonMode = Renderer::Backend::PolygonMode::LINE;
deviceCommandContext->SetGraphicsPipelineState(pipelineStateDesc);
deviceCommandContext->BeginPass(); deviceCommandContext->BeginPass();
Renderer::Backend::IShaderProgram* shaderTexLineNormal = shaderTechTexLineNormal->GetShader(); Renderer::Backend::IShaderProgram* shaderTexLineNormal = shaderTechnique->GetShader();
deviceCommandContext->SetTexture( deviceCommandContext->SetTexture(
shaderTexLineNormal->GetBindingSlot(str_losTex), los.GetTexture()); shaderTexLineNormal->GetBindingSlot(str_losTex), los.GetTexture());
@ -444,25 +493,15 @@ void OverlayRenderer::RenderTexturedOverlayLines(Renderer::Backend::IDeviceComma
deviceCommandContext->EndPass(); deviceCommandContext->EndPass();
} }
CShaderTechniquePtr shaderTechTexLineAlwaysVisible = GetOverlayLineShaderTechnique(m->defsOverlayLineAlwaysVisible); if (m->shaderTexLineAlwaysVisible.technique)
if (shaderTechTexLineAlwaysVisible)
{ {
Renderer::Backend::GraphicsPipelineStateDesc pipelineStateDesc = const CShaderTechniquePtr& shaderTechnique = m->shaderTexLineAlwaysVisible.GetTechnique();
shaderTechTexLineAlwaysVisible->GetGraphicsPipelineStateDesc(); deviceCommandContext->SetGraphicsPipelineState(
pipelineStateDesc.depthStencilState.depthWriteEnabled = false; shaderTechnique->GetGraphicsPipelineState());
pipelineStateDesc.blendState.enabled = true;
pipelineStateDesc.blendState.srcColorBlendFactor = pipelineStateDesc.blendState.srcAlphaBlendFactor =
Renderer::Backend::BlendFactor::SRC_ALPHA;
pipelineStateDesc.blendState.dstColorBlendFactor = pipelineStateDesc.blendState.dstAlphaBlendFactor =
Renderer::Backend::BlendFactor::ONE_MINUS_SRC_ALPHA;
pipelineStateDesc.blendState.colorBlendOp = pipelineStateDesc.blendState.alphaBlendOp =
Renderer::Backend::BlendOp::ADD;
if (g_Renderer.GetSceneRenderer().GetOverlayRenderMode() == WIREFRAME)
pipelineStateDesc.rasterizationState.polygonMode = Renderer::Backend::PolygonMode::LINE;
deviceCommandContext->SetGraphicsPipelineState(pipelineStateDesc);
deviceCommandContext->BeginPass(); deviceCommandContext->BeginPass();
Renderer::Backend::IShaderProgram* shaderTexLineAlwaysVisible = shaderTechTexLineAlwaysVisible->GetShader(); Renderer::Backend::IShaderProgram* shaderTexLineAlwaysVisible =
shaderTechnique->GetShader();
// TODO: losTex and losTransform are unused in the always visible shader; see if these can be safely omitted // TODO: losTex and losTransform are unused in the always visible shader; see if these can be safely omitted
deviceCommandContext->SetTexture( deviceCommandContext->SetTexture(
@ -506,27 +545,15 @@ void OverlayRenderer::RenderQuadOverlays(
if (m->quadBatchMap.empty()) if (m->quadBatchMap.empty())
return; return;
CShaderTechniquePtr shaderTech = GetOverlayLineShaderTechnique(m->defsQuadOverlay); if (!m->shaderQuadOverlay.technique)
if (!shaderTech)
return; return;
Renderer::Backend::GraphicsPipelineStateDesc pipelineStateDesc = const CShaderTechniquePtr& shaderTechnique = m->shaderQuadOverlay.GetTechnique();
shaderTech->GetGraphicsPipelineStateDesc(); deviceCommandContext->SetGraphicsPipelineState(
pipelineStateDesc.depthStencilState.depthWriteEnabled = false; shaderTechnique->GetGraphicsPipelineState());
pipelineStateDesc.blendState.enabled = true;
pipelineStateDesc.blendState.srcColorBlendFactor = pipelineStateDesc.blendState.srcAlphaBlendFactor =
Renderer::Backend::BlendFactor::SRC_ALPHA;
pipelineStateDesc.blendState.dstColorBlendFactor = pipelineStateDesc.blendState.dstAlphaBlendFactor =
Renderer::Backend::BlendFactor::ONE_MINUS_SRC_ALPHA;
pipelineStateDesc.blendState.colorBlendOp = pipelineStateDesc.blendState.alphaBlendOp =
Renderer::Backend::BlendOp::ADD;
if (g_Renderer.GetSceneRenderer().GetOverlayRenderMode() == WIREFRAME)
pipelineStateDesc.rasterizationState.polygonMode = Renderer::Backend::PolygonMode::LINE;
deviceCommandContext->SetGraphicsPipelineState(pipelineStateDesc);
deviceCommandContext->BeginPass(); deviceCommandContext->BeginPass();
Renderer::Backend::IShaderProgram* shader = shaderTech->GetShader(); Renderer::Backend::IShaderProgram* shader = shaderTechnique->GetShader();
CLOSTexture& los = g_Renderer.GetSceneRenderer().GetScene().GetLOSTexture(); CLOSTexture& los = g_Renderer.GetSceneRenderer().GetScene().GetLOSTexture();
@ -601,23 +628,12 @@ void OverlayRenderer::RenderForegroundOverlays(
const CVector3D right = -viewCamera.GetOrientation().GetLeft(); const CVector3D right = -viewCamera.GetOrientation().GetLeft();
const CVector3D up = viewCamera.GetOrientation().GetUp(); const CVector3D up = viewCamera.GetOrientation().GetUp();
CShaderTechniquePtr tech = g_Renderer.GetShaderManager().LoadEffect(str_foreground_overlay); const CShaderTechniquePtr& shaderTechnique = m->shaderForegroundOverlay.GetTechnique();
Renderer::Backend::GraphicsPipelineStateDesc pipelineStateDesc = deviceCommandContext->SetGraphicsPipelineState(
tech->GetGraphicsPipelineStateDesc(); shaderTechnique->GetGraphicsPipelineState());
pipelineStateDesc.depthStencilState.depthTestEnabled = false;
pipelineStateDesc.blendState.enabled = true;
pipelineStateDesc.blendState.srcColorBlendFactor = pipelineStateDesc.blendState.srcAlphaBlendFactor =
Renderer::Backend::BlendFactor::SRC_ALPHA;
pipelineStateDesc.blendState.dstColorBlendFactor = pipelineStateDesc.blendState.dstAlphaBlendFactor =
Renderer::Backend::BlendFactor::ONE_MINUS_SRC_ALPHA;
pipelineStateDesc.blendState.colorBlendOp = pipelineStateDesc.blendState.alphaBlendOp =
Renderer::Backend::BlendOp::ADD;
if (g_Renderer.GetSceneRenderer().GetOverlayRenderMode() == WIREFRAME)
pipelineStateDesc.rasterizationState.polygonMode = Renderer::Backend::PolygonMode::LINE;
deviceCommandContext->SetGraphicsPipelineState(pipelineStateDesc);
deviceCommandContext->BeginPass(); deviceCommandContext->BeginPass();
Renderer::Backend::IShaderProgram* shader = tech->GetShader(); Renderer::Backend::IShaderProgram* shader = shaderTechnique->GetShader();
const CMatrix3D transform = const CMatrix3D transform =
g_Renderer.GetSceneRenderer().GetViewCamera().GetViewProjection(); g_Renderer.GetSceneRenderer().GetViewCamera().GetViewProjection();
@ -750,27 +766,15 @@ void OverlayRenderer::RenderSphereOverlays(
{ {
PROFILE3_GPU("overlays (spheres)"); PROFILE3_GPU("overlays (spheres)");
if (m->spheres.empty()) if (m->spheres.empty() || m->shaderOverlaySolid.technique)
return; return;
Renderer::Backend::IShaderProgram* shader = nullptr; const CShaderTechniquePtr& shaderTechnique = m->shaderOverlaySolid.GetTechnique();
CShaderTechniquePtr tech; deviceCommandContext->SetGraphicsPipelineState(
shaderTechnique->GetGraphicsPipelineState());
tech = g_Renderer.GetShaderManager().LoadEffect(str_overlay_solid);
Renderer::Backend::GraphicsPipelineStateDesc pipelineStateDesc =
tech->GetGraphicsPipelineStateDesc();
pipelineStateDesc.depthStencilState.depthWriteEnabled = false;
pipelineStateDesc.blendState.enabled = true;
pipelineStateDesc.blendState.srcColorBlendFactor = pipelineStateDesc.blendState.srcAlphaBlendFactor =
Renderer::Backend::BlendFactor::SRC_ALPHA;
pipelineStateDesc.blendState.dstColorBlendFactor = pipelineStateDesc.blendState.dstAlphaBlendFactor =
Renderer::Backend::BlendFactor::ONE_MINUS_SRC_ALPHA;
pipelineStateDesc.blendState.colorBlendOp = pipelineStateDesc.blendState.alphaBlendOp =
Renderer::Backend::BlendOp::ADD;
deviceCommandContext->SetGraphicsPipelineState(pipelineStateDesc);
deviceCommandContext->BeginPass(); deviceCommandContext->BeginPass();
shader = tech->GetShader(); Renderer::Backend::IShaderProgram* shader = shaderTechnique->GetShader();
const CMatrix3D transform = const CMatrix3D transform =
g_Renderer.GetSceneRenderer().GetViewCamera().GetViewProjection(); g_Renderer.GetSceneRenderer().GetViewCamera().GetViewProjection();

View File

@ -135,7 +135,7 @@ private:
/** /**
* Helper method; renders all overlay lines currently registered in the internals. Batch- * Helper method; renders all overlay lines currently registered in the internals. Batch-
* renders textured overlay lines batched according to their visibility status by delegating * renders textured overlay lines batched according to their visibility status by delegating
* to RenderTexturedOverlayLines(CShaderProgramPtr, bool). * to RenderTexturedOverlayLines(IShaderProgram, bool).
*/ */
void RenderTexturedOverlayLines(Renderer::Backend::IDeviceCommandContext* deviceCommandContext); void RenderTexturedOverlayLines(Renderer::Backend::IDeviceCommandContext* deviceCommandContext);

View File

@ -161,7 +161,7 @@ void ParticleRenderer::RenderParticles(
if (lastTech) if (lastTech)
deviceCommandContext->EndPass(); deviceCommandContext->EndPass();
lastTech = currentTech; lastTech = currentTech;
deviceCommandContext->SetGraphicsPipelineState(lastTech->GetGraphicsPipelineStateDesc()); deviceCommandContext->SetGraphicsPipelineState(lastTech->GetGraphicsPipelineState());
deviceCommandContext->BeginPass(); deviceCommandContext->BeginPass();
Renderer::Backend::IShaderProgram* shader = lastTech->GetShader(); Renderer::Backend::IShaderProgram* shader = lastTech->GetShader();

View File

@ -772,7 +772,7 @@ void CPatchRData::RenderBases(
for (int pass = 0; pass < numPasses; ++pass) for (int pass = 0; pass < numPasses; ++pass)
{ {
deviceCommandContext->SetGraphicsPipelineState( deviceCommandContext->SetGraphicsPipelineState(
techBase->GetGraphicsPipelineStateDesc(pass)); techBase->GetGraphicsPipelineState(pass));
deviceCommandContext->BeginPass(); deviceCommandContext->BeginPass();
Renderer::Backend::IShaderProgram* shader = techBase->GetShader(pass); Renderer::Backend::IShaderProgram* shader = techBase->GetShader(pass);
TerrainRenderer::PrepareShader(deviceCommandContext, shader, shadow); TerrainRenderer::PrepareShader(deviceCommandContext, shader, shadow);
@ -978,8 +978,12 @@ void CPatchRData::RenderBlends(
{ {
CShaderDefines defines = contextBlend; CShaderDefines defines = contextBlend;
defines.SetMany(bestTex->GetMaterial().GetShaderDefines()); defines.SetMany(bestTex->GetMaterial().GetShaderDefines());
// TODO: move enabling blend to XML.
const CStrIntern shaderEffect = bestTex->GetMaterial().GetShaderEffect();
if (shaderEffect != str_terrain_base)
ONCE(LOGWARNING("Shader effect '%s' doesn't support semi-transparent terrain rendering.", shaderEffect.c_str()));
layer.m_ShaderTech = g_Renderer.GetShaderManager().LoadEffect( layer.m_ShaderTech = g_Renderer.GetShaderManager().LoadEffect(
bestTex->GetMaterial().GetShaderEffect(), defines); shaderEffect == str_terrain_base ? str_terrain_blend : shaderEffect, defines);
} }
batches.push_back(layer); batches.push_back(layer);
} }
@ -997,16 +1001,8 @@ void CPatchRData::RenderBlends(
const int numPasses = techBase->GetNumPasses(); const int numPasses = techBase->GetNumPasses();
for (int pass = 0; pass < numPasses; ++pass) for (int pass = 0; pass < numPasses; ++pass)
{ {
Renderer::Backend::GraphicsPipelineStateDesc pipelineStateDesc = deviceCommandContext->SetGraphicsPipelineState(
techBase->GetGraphicsPipelineStateDesc(pass); techBase->GetGraphicsPipelineState(pass));
pipelineStateDesc.blendState.enabled = true;
pipelineStateDesc.blendState.srcColorBlendFactor = pipelineStateDesc.blendState.srcAlphaBlendFactor =
Renderer::Backend::BlendFactor::SRC_ALPHA;
pipelineStateDesc.blendState.dstColorBlendFactor = pipelineStateDesc.blendState.dstAlphaBlendFactor =
Renderer::Backend::BlendFactor::ONE_MINUS_SRC_ALPHA;
pipelineStateDesc.blendState.colorBlendOp = pipelineStateDesc.blendState.alphaBlendOp =
Renderer::Backend::BlendOp::ADD;
deviceCommandContext->SetGraphicsPipelineState(pipelineStateDesc);
deviceCommandContext->BeginPass(); deviceCommandContext->BeginPass();
Renderer::Backend::IShaderProgram* shader = techBase->GetShader(pass); Renderer::Backend::IShaderProgram* shader = techBase->GetShader(pass);

View File

@ -230,7 +230,7 @@ void CPostprocManager::ApplyBlurDownscale2x(
CShaderTechniquePtr tech = g_Renderer.GetShaderManager().LoadEffect(str_bloom, defines); CShaderTechniquePtr tech = g_Renderer.GetShaderManager().LoadEffect(str_bloom, defines);
deviceCommandContext->SetGraphicsPipelineState( deviceCommandContext->SetGraphicsPipelineState(
tech->GetGraphicsPipelineStateDesc()); tech->GetGraphicsPipelineState());
deviceCommandContext->BeginPass(); deviceCommandContext->BeginPass();
Renderer::Backend::IShaderProgram* shader = tech->GetShader(); Renderer::Backend::IShaderProgram* shader = tech->GetShader();
@ -300,7 +300,7 @@ void CPostprocManager::ApplyBlurGauss(
CShaderTechniquePtr tech = g_Renderer.GetShaderManager().LoadEffect(str_bloom, defines2); CShaderTechniquePtr tech = g_Renderer.GetShaderManager().LoadEffect(str_bloom, defines2);
deviceCommandContext->SetGraphicsPipelineState( deviceCommandContext->SetGraphicsPipelineState(
tech->GetGraphicsPipelineStateDesc()); tech->GetGraphicsPipelineState());
deviceCommandContext->BeginPass(); deviceCommandContext->BeginPass();
Renderer::Backend::IShaderProgram* shader = tech->GetShader(); Renderer::Backend::IShaderProgram* shader = tech->GetShader();
deviceCommandContext->SetTexture( deviceCommandContext->SetTexture(
@ -357,7 +357,7 @@ void CPostprocManager::ApplyBlurGauss(
defines3.Add(str_BLOOM_PASS_V, str_1); defines3.Add(str_BLOOM_PASS_V, str_1);
tech = g_Renderer.GetShaderManager().LoadEffect(str_bloom, defines3); tech = g_Renderer.GetShaderManager().LoadEffect(str_bloom, defines3);
deviceCommandContext->SetGraphicsPipelineState( deviceCommandContext->SetGraphicsPipelineState(
tech->GetGraphicsPipelineStateDesc()); tech->GetGraphicsPipelineState());
deviceCommandContext->BeginPass(); deviceCommandContext->BeginPass();
shader = tech->GetShader(); shader = tech->GetShader();
@ -445,7 +445,7 @@ void CPostprocManager::ApplyEffect(
deviceCommandContext->SetViewports(1, &viewportRect); deviceCommandContext->SetViewports(1, &viewportRect);
deviceCommandContext->SetGraphicsPipelineState( deviceCommandContext->SetGraphicsPipelineState(
shaderTech->GetGraphicsPipelineStateDesc(pass)); shaderTech->GetGraphicsPipelineState(pass));
deviceCommandContext->BeginPass(); deviceCommandContext->BeginPass();
Renderer::Backend::IShaderProgram* shader = shaderTech->GetShader(pass); Renderer::Backend::IShaderProgram* shader = shaderTech->GetShader(pass);

View File

@ -457,9 +457,6 @@ void CRenderer::RenderFrameImpl(const bool renderGUI, const bool renderLogger)
{ {
g_Game->GetView()->Prepare(m->deviceCommandContext.get()); g_Game->GetView()->Prepare(m->deviceCommandContext.get());
m->deviceCommandContext->SetGraphicsPipelineState(
Renderer::Backend::MakeDefaultGraphicsPipelineStateDesc());
Renderer::Backend::IFramebuffer* framebuffer = nullptr; Renderer::Backend::IFramebuffer* framebuffer = nullptr;
CPostprocManager& postprocManager = g_Renderer.GetPostprocManager(); CPostprocManager& postprocManager = g_Renderer.GetPostprocManager();

View File

@ -575,8 +575,6 @@ void CSceneRenderer::RenderReflections(
screenScissor.x2 = static_cast<int>(ceil((reflectionScissor[1].X * 0.5f + 0.5f) * vpWidth)); screenScissor.x2 = static_cast<int>(ceil((reflectionScissor[1].X * 0.5f + 0.5f) * vpWidth));
screenScissor.y2 = static_cast<int>(ceil((reflectionScissor[1].Y * 0.5f + 0.5f) * vpHeight)); screenScissor.y2 = static_cast<int>(ceil((reflectionScissor[1].Y * 0.5f + 0.5f) * vpHeight));
deviceCommandContext->SetGraphicsPipelineState(
Renderer::Backend::MakeDefaultGraphicsPipelineStateDesc());
deviceCommandContext->BeginFramebufferPass(wm.m_ReflectionFramebuffer.get()); deviceCommandContext->BeginFramebufferPass(wm.m_ReflectionFramebuffer.get());
Renderer::Backend::IDeviceCommandContext::Rect viewportRect{}; Renderer::Backend::IDeviceCommandContext::Rect viewportRect{};
@ -652,8 +650,6 @@ void CSceneRenderer::RenderRefractions(
screenScissor.x2 = static_cast<int>(ceil((refractionScissor[1].X * 0.5f + 0.5f) * vpWidth)); screenScissor.x2 = static_cast<int>(ceil((refractionScissor[1].X * 0.5f + 0.5f) * vpWidth));
screenScissor.y2 = static_cast<int>(ceil((refractionScissor[1].Y * 0.5f + 0.5f) * vpHeight)); screenScissor.y2 = static_cast<int>(ceil((refractionScissor[1].Y * 0.5f + 0.5f) * vpHeight));
deviceCommandContext->SetGraphicsPipelineState(
Renderer::Backend::MakeDefaultGraphicsPipelineStateDesc());
deviceCommandContext->BeginFramebufferPass(wm.m_RefractionFramebuffer.get()); deviceCommandContext->BeginFramebufferPass(wm.m_RefractionFramebuffer.get());
Renderer::Backend::IDeviceCommandContext::Rect viewportRect{}; Renderer::Backend::IDeviceCommandContext::Rect viewportRect{};
@ -704,8 +700,6 @@ void CSceneRenderer::RenderSilhouettes(
// inverted depth test so any behind an occluder will get drawn in a constant // inverted depth test so any behind an occluder will get drawn in a constant
// color. // color.
deviceCommandContext->SetGraphicsPipelineState(
Renderer::Backend::MakeDefaultGraphicsPipelineStateDesc());
deviceCommandContext->ClearFramebuffer(false, true, true); deviceCommandContext->ClearFramebuffer(false, true, true);
// Render occluders: // Render occluders:

View File

@ -586,9 +586,6 @@ void ShadowMapInternals::CreateTexture()
void ShadowMap::BeginRender( void ShadowMap::BeginRender(
Renderer::Backend::IDeviceCommandContext* deviceCommandContext) Renderer::Backend::IDeviceCommandContext* deviceCommandContext)
{ {
deviceCommandContext->SetGraphicsPipelineState(
Renderer::Backend::MakeDefaultGraphicsPipelineStateDesc());
ENSURE(m->Framebuffer); ENSURE(m->Framebuffer);
deviceCommandContext->BeginFramebufferPass(m->Framebuffer.get()); deviceCommandContext->BeginFramebufferPass(m->Framebuffer.get());

View File

@ -469,15 +469,22 @@ void SilhouetteRenderer::RenderDebugOverlays(
proj.SetOrtho(0.f, g_MaxCoord, 0.f, g_MaxCoord, -1.f, 1000.f); proj.SetOrtho(0.f, g_MaxCoord, 0.f, g_MaxCoord, -1.f, 1000.f);
m = proj * m; m = proj * m;
CShaderTechniquePtr shaderTech = g_Renderer.GetShaderManager().LoadEffect(str_solid); if (!m_ShaderTech)
Renderer::Backend::GraphicsPipelineStateDesc pipelineStateDesc = {
shaderTech->GetGraphicsPipelineStateDesc(); m_ShaderTech = g_Renderer.GetShaderManager().LoadEffect(
deviceCommandContext->BeginPass(); str_solid, {},
pipelineStateDesc.rasterizationState.polygonMode = Renderer::Backend::PolygonMode::LINE; [](Renderer::Backend::SGraphicsPipelineStateDesc& pipelineStateDesc)
pipelineStateDesc.rasterizationState.cullMode = Renderer::Backend::CullMode::NONE; {
deviceCommandContext->SetGraphicsPipelineState(pipelineStateDesc); pipelineStateDesc.rasterizationState.polygonMode = Renderer::Backend::PolygonMode::LINE;
pipelineStateDesc.rasterizationState.cullMode = Renderer::Backend::CullMode::NONE;
});
}
Renderer::Backend::IShaderProgram* shader = shaderTech->GetShader(); deviceCommandContext->BeginPass();
deviceCommandContext->SetGraphicsPipelineState(
m_ShaderTech->GetGraphicsPipelineState());
Renderer::Backend::IShaderProgram* shader = m_ShaderTech->GetShader();
deviceCommandContext->SetUniform( deviceCommandContext->SetUniform(
shader->GetBindingSlot(str_transform), proj.AsFloatArray()); shader->GetBindingSlot(str_transform), proj.AsFloatArray());

View File

@ -19,6 +19,7 @@
#define INCLUDED_SILHOUETTERENDERER #define INCLUDED_SILHOUETTERENDERER
#include "graphics/Overlay.h" #include "graphics/Overlay.h"
#include "graphics/ShaderTechniquePtr.h"
#include "maths/BoundingBoxAligned.h" #include "maths/BoundingBoxAligned.h"
#include "renderer/backend/IDeviceCommandContext.h" #include "renderer/backend/IDeviceCommandContext.h"
@ -75,6 +76,8 @@ private:
std::vector<DebugRect> m_DebugRects; std::vector<DebugRect> m_DebugRects;
std::vector<SOverlaySphere> m_DebugSpheres; std::vector<SOverlaySphere> m_DebugSpheres;
CShaderTechniquePtr m_ShaderTech;
}; };
#endif // INCLUDED_SILHOUETTERENDERER #endif // INCLUDED_SILHOUETTERENDERER

View File

@ -222,7 +222,7 @@ void SkyManager::RenderSky(
CShaderTechniquePtr skytech = CShaderTechniquePtr skytech =
g_Renderer.GetShaderManager().LoadEffect(str_sky_simple); g_Renderer.GetShaderManager().LoadEffect(str_sky_simple);
deviceCommandContext->SetGraphicsPipelineState( deviceCommandContext->SetGraphicsPipelineState(
skytech->GetGraphicsPipelineStateDesc()); skytech->GetGraphicsPipelineState());
deviceCommandContext->BeginPass(); deviceCommandContext->BeginPass();
Renderer::Backend::IShaderProgram* shader = skytech->GetShader(); Renderer::Backend::IShaderProgram* shader = skytech->GetShader();
deviceCommandContext->SetTexture( deviceCommandContext->SetTexture(

View File

@ -39,9 +39,55 @@
#include <algorithm> #include <algorithm>
// Global overlay list management: namespace
{
static std::vector<std::pair<ITerrainOverlay*, int> > g_TerrainOverlayList; // Global overlay list management:
std::vector<std::pair<ITerrainOverlay*, int>> g_TerrainOverlayList;
void AdjustOverlayGraphicsPipelineState(
Renderer::Backend::SGraphicsPipelineStateDesc& pipelineStateDesc, const bool drawHidden)
{
pipelineStateDesc.depthStencilState.depthTestEnabled = !drawHidden;
pipelineStateDesc.blendState.enabled = true;
pipelineStateDesc.blendState.srcColorBlendFactor = pipelineStateDesc.blendState.srcAlphaBlendFactor =
Renderer::Backend::BlendFactor::SRC_ALPHA;
pipelineStateDesc.blendState.dstColorBlendFactor = pipelineStateDesc.blendState.dstAlphaBlendFactor =
Renderer::Backend::BlendFactor::ONE_MINUS_SRC_ALPHA;
pipelineStateDesc.blendState.colorBlendOp = pipelineStateDesc.blendState.alphaBlendOp =
Renderer::Backend::BlendOp::ADD;
pipelineStateDesc.rasterizationState.cullMode =
drawHidden ? Renderer::Backend::CullMode::NONE : Renderer::Backend::CullMode::BACK;
}
CShaderTechniquePtr CreateOverlayTileShaderTechnique(const bool drawHidden)
{
return g_Renderer.GetShaderManager().LoadEffect(
str_debug_line, {},
[drawHidden](Renderer::Backend::SGraphicsPipelineStateDesc& pipelineStateDesc)
{
AdjustOverlayGraphicsPipelineState(pipelineStateDesc, drawHidden);
// To ensure that outlines are drawn on top of the terrain correctly (and
// don't Z-fight and flicker nastily), use detph bias to pull them towards
// the camera.
pipelineStateDesc.rasterizationState.depthBiasEnabled = true;
pipelineStateDesc.rasterizationState.depthBiasConstantFactor = -1.0f;
pipelineStateDesc.rasterizationState.depthBiasSlopeFactor = -1.0f;
});
}
CShaderTechniquePtr CreateOverlayOutlineShaderTechnique(const bool drawHidden)
{
return g_Renderer.GetShaderManager().LoadEffect(
str_debug_line, {},
[drawHidden](Renderer::Backend::SGraphicsPipelineStateDesc& pipelineStateDesc)
{
AdjustOverlayGraphicsPipelineState(pipelineStateDesc, drawHidden);
pipelineStateDesc.rasterizationState.polygonMode = Renderer::Backend::PolygonMode::LINE;
});
}
} // anonymous namespace
ITerrainOverlay::ITerrainOverlay(int priority) ITerrainOverlay::ITerrainOverlay(int priority)
{ {
@ -93,9 +139,15 @@ void ITerrainOverlay::RenderOverlaysAfterWater(
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
TerrainOverlay::TerrainOverlay(const CSimContext& simContext, int priority /* = 100 */) TerrainOverlay::TerrainOverlay(
const CSimContext& simContext, int priority /* = 100 */)
: ITerrainOverlay(priority), m_Terrain(&simContext.GetTerrain()) : ITerrainOverlay(priority), m_Terrain(&simContext.GetTerrain())
{ {
m_OverlayTechTile = CreateOverlayTileShaderTechnique(false);
m_OverlayTechTileHidden = CreateOverlayTileShaderTechnique(true);
m_OverlayTechOutline = CreateOverlayOutlineShaderTechnique(false);
m_OverlayTechOutlineHidden = CreateOverlayOutlineShaderTechnique(true);
} }
void TerrainOverlay::StartRender() void TerrainOverlay::StartRender()
@ -188,30 +240,12 @@ void TerrainOverlay::RenderTile(
} }
#undef ADD #undef ADD
CShaderTechniquePtr overlayTech = const CShaderTechniquePtr& shaderTechnique = drawHidden ? m_OverlayTechTileHidden : m_OverlayTechTile;
g_Renderer.GetShaderManager().LoadEffect(str_debug_line); deviceCommandContext->SetGraphicsPipelineState(
Renderer::Backend::GraphicsPipelineStateDesc pipelineStateDesc = shaderTechnique->GetGraphicsPipelineState());
overlayTech->GetGraphicsPipelineStateDesc();
pipelineStateDesc.depthStencilState.depthTestEnabled = !drawHidden;
pipelineStateDesc.blendState.enabled = true;
pipelineStateDesc.blendState.srcColorBlendFactor = pipelineStateDesc.blendState.srcAlphaBlendFactor =
Renderer::Backend::BlendFactor::SRC_ALPHA;
pipelineStateDesc.blendState.dstColorBlendFactor = pipelineStateDesc.blendState.dstAlphaBlendFactor =
Renderer::Backend::BlendFactor::ONE_MINUS_SRC_ALPHA;
pipelineStateDesc.blendState.colorBlendOp = pipelineStateDesc.blendState.alphaBlendOp =
Renderer::Backend::BlendOp::ADD;
pipelineStateDesc.rasterizationState.cullMode =
drawHidden ? Renderer::Backend::CullMode::NONE : Renderer::Backend::CullMode::BACK;
// To ensure that outlines are drawn on top of the terrain correctly (and
// don't Z-fight and flicker nastily), use detph bias to pull them towards
// the camera.
pipelineStateDesc.rasterizationState.depthBiasEnabled = true;
pipelineStateDesc.rasterizationState.depthBiasConstantFactor = -1.0f;
pipelineStateDesc.rasterizationState.depthBiasSlopeFactor = -1.0f;
deviceCommandContext->SetGraphicsPipelineState(pipelineStateDesc);
deviceCommandContext->BeginPass(); deviceCommandContext->BeginPass();
Renderer::Backend::IShaderProgram* overlayShader = overlayTech->GetShader(); Renderer::Backend::IShaderProgram* overlayShader = shaderTechnique->GetShader();
const CMatrix3D transform = const CMatrix3D transform =
g_Renderer.GetSceneRenderer().GetViewCamera().GetViewProjection(); g_Renderer.GetSceneRenderer().GetViewCamera().GetViewProjection();
@ -260,25 +294,12 @@ void TerrainOverlay::RenderTileOutline(
ADD(i, j + 1); ADD(i, j + 1);
#undef ADD #undef ADD
CShaderTechniquePtr overlayTech = const CShaderTechniquePtr& shaderTechnique = drawHidden ? m_OverlayTechOutlineHidden : m_OverlayTechOutline;
g_Renderer.GetShaderManager().LoadEffect(str_debug_line); deviceCommandContext->SetGraphicsPipelineState(
Renderer::Backend::GraphicsPipelineStateDesc pipelineStateDesc = shaderTechnique->GetGraphicsPipelineState());
overlayTech->GetGraphicsPipelineStateDesc();
pipelineStateDesc.depthStencilState.depthTestEnabled = !drawHidden;
pipelineStateDesc.blendState.enabled = true;
pipelineStateDesc.blendState.srcColorBlendFactor = pipelineStateDesc.blendState.srcAlphaBlendFactor =
Renderer::Backend::BlendFactor::SRC_ALPHA;
pipelineStateDesc.blendState.dstColorBlendFactor = pipelineStateDesc.blendState.dstAlphaBlendFactor =
Renderer::Backend::BlendFactor::ONE_MINUS_SRC_ALPHA;
pipelineStateDesc.blendState.colorBlendOp = pipelineStateDesc.blendState.alphaBlendOp =
Renderer::Backend::BlendOp::ADD;
pipelineStateDesc.rasterizationState.cullMode =
drawHidden ? Renderer::Backend::CullMode::NONE : Renderer::Backend::CullMode::BACK;
pipelineStateDesc.rasterizationState.polygonMode = Renderer::Backend::PolygonMode::LINE;
deviceCommandContext->SetGraphicsPipelineState(pipelineStateDesc);
deviceCommandContext->BeginPass(); deviceCommandContext->BeginPass();
Renderer::Backend::IShaderProgram* overlayShader = overlayTech->GetShader(); Renderer::Backend::IShaderProgram* overlayShader = shaderTechnique->GetShader();
const CMatrix3D transform = const CMatrix3D transform =
g_Renderer.GetSceneRenderer().GetViewCamera().GetViewProjection(); g_Renderer.GetSceneRenderer().GetViewCamera().GetViewProjection();

View File

@ -23,8 +23,10 @@
#ifndef INCLUDED_TERRAINOVERLAY #ifndef INCLUDED_TERRAINOVERLAY
#define INCLUDED_TERRAINOVERLAY #define INCLUDED_TERRAINOVERLAY
#include "graphics/ShaderTechniquePtr.h"
#include "renderer/backend/ITexture.h" #include "renderer/backend/ITexture.h"
#include "renderer/backend/IDeviceCommandContext.h" #include "renderer/backend/IDeviceCommandContext.h"
#include "renderer/backend/PipelineState.h"
struct CColor; struct CColor;
struct SColor4ub; struct SColor4ub;
@ -179,6 +181,9 @@ private:
ssize_t m_i, m_j; ssize_t m_i, m_j;
CTerrain* m_Terrain; CTerrain* m_Terrain;
CShaderTechniquePtr m_OverlayTechTile, m_OverlayTechTileHidden;
CShaderTechniquePtr m_OverlayTechOutline, m_OverlayTechOutlineHidden;
}; };
/** /**

View File

@ -40,6 +40,7 @@
#include "ps/Profile.h" #include "ps/Profile.h"
#include "ps/World.h" #include "ps/World.h"
#include "renderer/backend/IDevice.h" #include "renderer/backend/IDevice.h"
#include "renderer/backend/PipelineState.h"
#include "renderer/DecalRData.h" #include "renderer/DecalRData.h"
#include "renderer/PatchRData.h" #include "renderer/PatchRData.h"
#include "renderer/Renderer.h" #include "renderer/Renderer.h"
@ -50,6 +51,8 @@
#include "renderer/VertexArray.h" #include "renderer/VertexArray.h"
#include "renderer/WaterManager.h" #include "renderer/WaterManager.h"
#include <memory>
/** /**
* TerrainRenderer keeps track of which phase it is in, to detect * TerrainRenderer keeps track of which phase it is in, to detect
* when Submit, PrepareForRendering etc. are called in the wrong order. * when Submit, PrepareForRendering etc. are called in the wrong order.
@ -78,6 +81,8 @@ struct TerrainRendererInternals
/// Fancy water shader /// Fancy water shader
CShaderTechniquePtr fancyWaterTech; CShaderTechniquePtr fancyWaterTech;
CShaderTechniquePtr shaderTechniqueSolid, shaderTechniqueSolidDepthTest;
CSimulation2* simulation; CSimulation2* simulation;
}; };
@ -173,7 +178,7 @@ void TerrainRenderer::RenderTerrainOverlayTexture(
CShaderTechniquePtr debugOverlayTech = CShaderTechniquePtr debugOverlayTech =
g_Renderer.GetShaderManager().LoadEffect(str_debug_overlay); g_Renderer.GetShaderManager().LoadEffect(str_debug_overlay);
deviceCommandContext->SetGraphicsPipelineState( deviceCommandContext->SetGraphicsPipelineState(
debugOverlayTech->GetGraphicsPipelineStateDesc()); debugOverlayTech->GetGraphicsPipelineState());
deviceCommandContext->BeginPass(); deviceCommandContext->BeginPass();
Renderer::Backend::IShaderProgram* debugOverlayShader = debugOverlayTech->GetShader(); Renderer::Backend::IShaderProgram* debugOverlayShader = debugOverlayTech->GetShader();
@ -284,15 +289,22 @@ void TerrainRenderer::RenderTerrainShader(
if (visiblePatches.empty() && visibleDecals.empty()) if (visiblePatches.empty() && visibleDecals.empty())
return; return;
if (!m->shaderTechniqueSolid)
{
m->shaderTechniqueSolid = g_Renderer.GetShaderManager().LoadEffect(
str_solid, {},
[](Renderer::Backend::SGraphicsPipelineStateDesc& pipelineStateDesc)
{
pipelineStateDesc.rasterizationState.cullMode = Renderer::Backend::CullMode::NONE;
});
}
// render the solid black sides of the map first // render the solid black sides of the map first
CShaderTechniquePtr techSolid = g_Renderer.GetShaderManager().LoadEffect(str_solid); deviceCommandContext->SetGraphicsPipelineState(
Renderer::Backend::GraphicsPipelineStateDesc solidPipelineStateDesc = m->shaderTechniqueSolid->GetGraphicsPipelineState());
techSolid->GetGraphicsPipelineStateDesc();
solidPipelineStateDesc.rasterizationState.cullMode = Renderer::Backend::CullMode::NONE;
deviceCommandContext->SetGraphicsPipelineState(solidPipelineStateDesc);
deviceCommandContext->BeginPass(); deviceCommandContext->BeginPass();
Renderer::Backend::IShaderProgram* shaderSolid = techSolid->GetShader(); Renderer::Backend::IShaderProgram* shaderSolid = m->shaderTechniqueSolid->GetShader();
const CMatrix3D transform = const CMatrix3D transform =
g_Renderer.GetSceneRenderer().GetViewCamera().GetViewProjection(); g_Renderer.GetSceneRenderer().GetViewCamera().GetViewProjection();
deviceCommandContext->SetUniform( deviceCommandContext->SetUniform(
@ -328,7 +340,7 @@ void TerrainRenderer::RenderPatches(
CShaderTechniquePtr solidTech = g_Renderer.GetShaderManager().LoadEffect(str_terrain_solid, defines); CShaderTechniquePtr solidTech = g_Renderer.GetShaderManager().LoadEffect(str_terrain_solid, defines);
deviceCommandContext->SetGraphicsPipelineState( deviceCommandContext->SetGraphicsPipelineState(
solidTech->GetGraphicsPipelineStateDesc()); solidTech->GetGraphicsPipelineState());
deviceCommandContext->BeginPass(); deviceCommandContext->BeginPass();
Renderer::Backend::IShaderProgram* solidShader = solidTech->GetShader(); Renderer::Backend::IShaderProgram* solidShader = solidTech->GetShader();
@ -436,7 +448,7 @@ bool TerrainRenderer::RenderFancyWater(
const float repeatPeriod = waterManager.m_RepeatPeriod; const float repeatPeriod = waterManager.m_RepeatPeriod;
deviceCommandContext->SetGraphicsPipelineState( deviceCommandContext->SetGraphicsPipelineState(
m->fancyWaterTech->GetGraphicsPipelineStateDesc()); m->fancyWaterTech->GetGraphicsPipelineState());
deviceCommandContext->BeginPass(); deviceCommandContext->BeginPass();
Renderer::Backend::IShaderProgram* fancyWaterShader = m->fancyWaterTech->GetShader(); Renderer::Backend::IShaderProgram* fancyWaterShader = m->fancyWaterTech->GetShader();
@ -622,7 +634,7 @@ void TerrainRenderer::RenderSimpleWater(
CShaderTechniquePtr waterSimpleTech = CShaderTechniquePtr waterSimpleTech =
g_Renderer.GetShaderManager().LoadEffect(str_water_simple, context); g_Renderer.GetShaderManager().LoadEffect(str_water_simple, context);
deviceCommandContext->SetGraphicsPipelineState( deviceCommandContext->SetGraphicsPipelineState(
waterSimpleTech->GetGraphicsPipelineStateDesc()); waterSimpleTech->GetGraphicsPipelineState());
deviceCommandContext->BeginPass(); deviceCommandContext->BeginPass();
Renderer::Backend::IShaderProgram* waterSimpleShader = waterSimpleTech->GetShader(); Renderer::Backend::IShaderProgram* waterSimpleShader = waterSimpleTech->GetShader();
@ -680,21 +692,28 @@ void TerrainRenderer::RenderWaterFoamOccluders(
if (!waterManager.WillRenderFancyWater()) if (!waterManager.WillRenderFancyWater())
return; return;
if (!m->shaderTechniqueSolidDepthTest)
{
m->shaderTechniqueSolidDepthTest = g_Renderer.GetShaderManager().LoadEffect(
str_solid, {},
[](Renderer::Backend::SGraphicsPipelineStateDesc& pipelineStateDesc)
{
pipelineStateDesc.depthStencilState.depthTestEnabled = true;
pipelineStateDesc.rasterizationState.cullMode = Renderer::Backend::CullMode::NONE;
});
}
GPU_SCOPED_LABEL(deviceCommandContext, "Render water foam occluders"); GPU_SCOPED_LABEL(deviceCommandContext, "Render water foam occluders");
// Render normals and foam to a framebuffer if we're using fancy effects. // Render normals and foam to a framebuffer if we're using fancy effects.
deviceCommandContext->BeginFramebufferPass(waterManager.m_FancyEffectsFramebuffer.get()); deviceCommandContext->BeginFramebufferPass(waterManager.m_FancyEffectsFramebuffer.get());
// Overwrite waves that would be behind the ground. // Overwrite waves that would be behind the ground.
CShaderTechniquePtr dummyTech = g_Renderer.GetShaderManager().LoadEffect(str_solid); deviceCommandContext->SetGraphicsPipelineState(
Renderer::Backend::GraphicsPipelineStateDesc pipelineStateDesc = m->shaderTechniqueSolidDepthTest->GetGraphicsPipelineState());
dummyTech->GetGraphicsPipelineStateDesc();
pipelineStateDesc.depthStencilState.depthTestEnabled = true;
pipelineStateDesc.rasterizationState.cullMode = Renderer::Backend::CullMode::NONE;
deviceCommandContext->SetGraphicsPipelineState(pipelineStateDesc);
deviceCommandContext->BeginPass(); deviceCommandContext->BeginPass();
Renderer::Backend::IShaderProgram* dummyShader = dummyTech->GetShader(); Renderer::Backend::IShaderProgram* dummyShader = m->shaderTechniqueSolidDepthTest->GetShader();
const CMatrix3D transform = sceneRenderer.GetViewCamera().GetViewProjection(); const CMatrix3D transform = sceneRenderer.GetViewCamera().GetViewProjection();
deviceCommandContext->SetUniform( deviceCommandContext->SetUniform(

View File

@ -840,13 +840,11 @@ void WaterManager::RenderWaves(
GPU_SCOPED_LABEL(deviceCommandContext, "Render Waves"); GPU_SCOPED_LABEL(deviceCommandContext, "Render Waves");
deviceCommandContext->SetGraphicsPipelineState(
Renderer::Backend::MakeDefaultGraphicsPipelineStateDesc());
deviceCommandContext->BeginFramebufferPass(m_FancyEffectsFramebuffer.get()); deviceCommandContext->BeginFramebufferPass(m_FancyEffectsFramebuffer.get());
CShaderTechniquePtr tech = g_Renderer.GetShaderManager().LoadEffect(str_water_waves); CShaderTechniquePtr tech = g_Renderer.GetShaderManager().LoadEffect(str_water_waves);
deviceCommandContext->SetGraphicsPipelineState( deviceCommandContext->SetGraphicsPipelineState(
tech->GetGraphicsPipelineStateDesc()); tech->GetGraphicsPipelineState());
deviceCommandContext->BeginPass(); deviceCommandContext->BeginPass();
Renderer::Backend::IShaderProgram* shader = tech->GetShader(); Renderer::Backend::IShaderProgram* shader = tech->GetShader();

View File

@ -27,6 +27,7 @@
#include "renderer/backend/IFramebuffer.h" #include "renderer/backend/IFramebuffer.h"
#include "renderer/backend/IShaderProgram.h" #include "renderer/backend/IShaderProgram.h"
#include "renderer/backend/ITexture.h" #include "renderer/backend/ITexture.h"
#include "renderer/backend/PipelineState.h"
#include "scriptinterface/ScriptForward.h" #include "scriptinterface/ScriptForward.h"
#include <memory> #include <memory>
@ -74,6 +75,13 @@ public:
virtual std::unique_ptr<IDeviceCommandContext> CreateCommandContext() = 0; virtual std::unique_ptr<IDeviceCommandContext> CreateCommandContext() = 0;
/**
* Creates a graphics pipeline state. It's a caller responsibility to
* guarantee a lifespan of IShaderProgram stored in the description.
*/
virtual std::unique_ptr<IGraphicsPipelineState> CreateGraphicsPipelineState(
const SGraphicsPipelineStateDesc& pipelineStateDesc) = 0;
virtual std::unique_ptr<ITexture> CreateTexture( virtual std::unique_ptr<ITexture> CreateTexture(
const char* name, const ITexture::Type type, const uint32_t usage, const char* name, const ITexture::Type type, const uint32_t usage,
const Format format, const uint32_t width, const uint32_t height, const Format format, const uint32_t width, const uint32_t height,

View File

@ -40,7 +40,7 @@ class ITexture;
class IDeviceCommandContext : public IDeviceObject<IDeviceCommandContext> class IDeviceCommandContext : public IDeviceObject<IDeviceCommandContext>
{ {
public: public:
virtual void SetGraphicsPipelineState(const GraphicsPipelineStateDesc& pipelineStateDesc) = 0; virtual void SetGraphicsPipelineState(IGraphicsPipelineState* pipelineState) = 0;
virtual void BlitFramebuffer( virtual void BlitFramebuffer(
IFramebuffer* destinationFramebuffer, IFramebuffer* sourceFramebuffer) = 0; IFramebuffer* destinationFramebuffer, IFramebuffer* sourceFramebuffer) = 0;

View File

@ -27,9 +27,9 @@ namespace Renderer
namespace Backend namespace Backend
{ {
GraphicsPipelineStateDesc MakeDefaultGraphicsPipelineStateDesc() SGraphicsPipelineStateDesc MakeDefaultGraphicsPipelineStateDesc()
{ {
GraphicsPipelineStateDesc desc{}; SGraphicsPipelineStateDesc desc{};
desc.shaderProgram = nullptr; desc.shaderProgram = nullptr;

View File

@ -20,6 +20,7 @@
#include "graphics/Color.h" #include "graphics/Color.h"
#include "renderer/backend/CompareOp.h" #include "renderer/backend/CompareOp.h"
#include "renderer/backend/IDeviceObject.h"
#include "renderer/backend/IShaderProgram.h" #include "renderer/backend/IShaderProgram.h"
class CStr; class CStr;
@ -53,7 +54,7 @@ enum class StencilOp
DECREMENT_AND_WRAP DECREMENT_AND_WRAP
}; };
struct StencilOpState struct SStencilOpState
{ {
StencilOp failOp; StencilOp failOp;
StencilOp passOp; StencilOp passOp;
@ -61,7 +62,7 @@ struct StencilOpState
CompareOp compareOp; CompareOp compareOp;
}; };
struct DepthStencilStateDesc struct SDepthStencilStateDesc
{ {
bool depthTestEnabled; bool depthTestEnabled;
CompareOp depthCompareOp; CompareOp depthCompareOp;
@ -70,8 +71,8 @@ struct DepthStencilStateDesc
uint32_t stencilReadMask; uint32_t stencilReadMask;
uint32_t stencilWriteMask; uint32_t stencilWriteMask;
uint32_t stencilReference; uint32_t stencilReference;
StencilOpState stencilFrontFace; SStencilOpState stencilFrontFace;
StencilOpState stencilBackFace; SStencilOpState stencilBackFace;
}; };
// TODO: add per constant description. // TODO: add per constant description.
@ -118,7 +119,7 @@ constexpr uint8_t BLUE = 0x04;
constexpr uint8_t ALPHA = 0x08; constexpr uint8_t ALPHA = 0x08;
} // namespace ColorWriteMask } // namespace ColorWriteMask
struct BlendStateDesc struct SBlendStateDesc
{ {
bool enabled; bool enabled;
BlendFactor srcColorBlendFactor; BlendFactor srcColorBlendFactor;
@ -150,7 +151,7 @@ enum class FrontFace
CLOCKWISE CLOCKWISE
}; };
struct RasterizationStateDesc struct SRasterizationStateDesc
{ {
PolygonMode polygonMode; PolygonMode polygonMode;
CullMode cullMode; CullMode cullMode;
@ -160,19 +161,19 @@ struct RasterizationStateDesc
float depthBiasSlopeFactor; float depthBiasSlopeFactor;
}; };
struct GraphicsPipelineStateDesc struct SGraphicsPipelineStateDesc
{ {
// It's a backend client reponsibility to keep the shader program alive // It's a backend client reponsibility to keep the shader program alive
// while it's bound. // while it's bound.
IShaderProgram* shaderProgram; IShaderProgram* shaderProgram;
DepthStencilStateDesc depthStencilState; SDepthStencilStateDesc depthStencilState;
BlendStateDesc blendState; SBlendStateDesc blendState;
RasterizationStateDesc rasterizationState; SRasterizationStateDesc rasterizationState;
}; };
// We don't provide additional helpers intentionally because all custom states // We don't provide additional helpers intentionally because all custom states
// should be described with a related shader and should be switched together. // should be described with a related shader and should be switched together.
GraphicsPipelineStateDesc MakeDefaultGraphicsPipelineStateDesc(); SGraphicsPipelineStateDesc MakeDefaultGraphicsPipelineStateDesc();
StencilOp ParseStencilOp(const CStr& str); StencilOp ParseStencilOp(const CStr& str);
@ -183,6 +184,15 @@ PolygonMode ParsePolygonMode(const CStr& str);
CullMode ParseCullMode(const CStr& str); CullMode ParseCullMode(const CStr& str);
FrontFace ParseFrontFace(const CStr& str); FrontFace ParseFrontFace(const CStr& str);
/**
* A holder for precompiled graphics pipeline description.
*/
class IGraphicsPipelineState : public IDeviceObject<IGraphicsPipelineState>
{
public:
virtual IShaderProgram* GetShaderProgram() const = 0;
};
} // namespace Backend } // namespace Backend
} // namespace Renderer } // namespace Renderer

View File

@ -22,6 +22,7 @@
#include "renderer/backend/dummy/Buffer.h" #include "renderer/backend/dummy/Buffer.h"
#include "renderer/backend/dummy/DeviceCommandContext.h" #include "renderer/backend/dummy/DeviceCommandContext.h"
#include "renderer/backend/dummy/Framebuffer.h" #include "renderer/backend/dummy/Framebuffer.h"
#include "renderer/backend/dummy/PipelineState.h"
#include "renderer/backend/dummy/ShaderProgram.h" #include "renderer/backend/dummy/ShaderProgram.h"
#include "renderer/backend/dummy/Texture.h" #include "renderer/backend/dummy/Texture.h"
#include "scriptinterface/JSON.h" #include "scriptinterface/JSON.h"
@ -73,6 +74,12 @@ std::unique_ptr<IDeviceCommandContext> CDevice::CreateCommandContext()
return CDeviceCommandContext::Create(this); return CDeviceCommandContext::Create(this);
} }
std::unique_ptr<IGraphicsPipelineState> CDevice::CreateGraphicsPipelineState(
const SGraphicsPipelineStateDesc& pipelineStateDesc)
{
return CGraphicsPipelineState::Create(this, pipelineStateDesc);
}
std::unique_ptr<ITexture> CDevice::CreateTexture( std::unique_ptr<ITexture> CDevice::CreateTexture(
const char* UNUSED(name), const CTexture::Type type, const uint32_t usage, const char* UNUSED(name), const CTexture::Type type, const uint32_t usage,
const Format format, const uint32_t width, const uint32_t height, const Format format, const uint32_t width, const uint32_t height,

View File

@ -21,6 +21,10 @@
#include "renderer/backend/dummy/DeviceForward.h" #include "renderer/backend/dummy/DeviceForward.h"
#include "renderer/backend/IDevice.h" #include "renderer/backend/IDevice.h"
#include <memory>
#include <string>
#include <vector>
class CShaderDefines; class CShaderDefines;
namespace Renderer namespace Renderer
@ -51,6 +55,9 @@ public:
std::unique_ptr<IDeviceCommandContext> CreateCommandContext() override; std::unique_ptr<IDeviceCommandContext> CreateCommandContext() override;
std::unique_ptr<IGraphicsPipelineState> CreateGraphicsPipelineState(
const SGraphicsPipelineStateDesc& pipelineStateDesc) override;
std::unique_ptr<ITexture> CreateTexture( std::unique_ptr<ITexture> CreateTexture(
const char* name, const ITexture::Type type, const uint32_t usage, const char* name, const ITexture::Type type, const uint32_t usage,
const Format format, const uint32_t width, const uint32_t height, const Format format, const uint32_t width, const uint32_t height,

View File

@ -52,7 +52,7 @@ IDevice* CDeviceCommandContext::GetDevice()
} }
void CDeviceCommandContext::SetGraphicsPipelineState( void CDeviceCommandContext::SetGraphicsPipelineState(
const GraphicsPipelineStateDesc&) IGraphicsPipelineState*)
{ {
} }

View File

@ -46,7 +46,7 @@ public:
IDevice* GetDevice() override; IDevice* GetDevice() override;
void SetGraphicsPipelineState(const GraphicsPipelineStateDesc& pipelineStateDesc) override; void SetGraphicsPipelineState(IGraphicsPipelineState* pipelineState) override;
void BlitFramebuffer(IFramebuffer* destinationFramebuffer, IFramebuffer* sourceFramebuffer) override; void BlitFramebuffer(IFramebuffer* destinationFramebuffer, IFramebuffer* sourceFramebuffer) override;

View File

@ -0,0 +1,52 @@
/* Copyright (C) 2022 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. 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 2 of the License, or
* (at your option) any later version.
*
* 0 A.D. 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 0 A.D. If not, see <http://www.gnu.org/licenses/>.
*/
#include "precompiled.h"
#include "PipelineState.h"
#include "renderer/backend/dummy/Device.h"
namespace Renderer
{
namespace Backend
{
namespace Dummy
{
// static
std::unique_ptr<CGraphicsPipelineState> CGraphicsPipelineState::Create(
CDevice* device, const SGraphicsPipelineStateDesc& desc)
{
std::unique_ptr<CGraphicsPipelineState> pipelineState{new CGraphicsPipelineState()};
pipelineState->m_Device = device;
pipelineState->m_Desc = desc;
return pipelineState;
}
IDevice* CGraphicsPipelineState::GetDevice()
{
return m_Device;
}
} // namespace Dummy
} // namespace Backend
} // namespace Renderer

View File

@ -0,0 +1,67 @@
/* Copyright (C) 2022 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. 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 2 of the License, or
* (at your option) any later version.
*
* 0 A.D. 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 0 A.D. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef INCLUDED_RENDERER_BACKEND_DUMMY_PIPELINESTATE
#define INCLUDED_RENDERER_BACKEND_DUMMY_PIPELINESTATE
#include "renderer/backend/PipelineState.h"
#include <cstdint>
#include <memory>
namespace Renderer
{
namespace Backend
{
namespace Dummy
{
class CDevice;
class CGraphicsPipelineState final : public IGraphicsPipelineState
{
public:
~CGraphicsPipelineState() override = default;
IDevice* GetDevice() override;
IShaderProgram* GetShaderProgram() const override { return m_Desc.shaderProgram; }
const SGraphicsPipelineStateDesc& GetDesc() const { return m_Desc; }
private:
friend class CDevice;
static std::unique_ptr<CGraphicsPipelineState> Create(
CDevice* device, const SGraphicsPipelineStateDesc& desc);
CGraphicsPipelineState() = default;
CDevice* m_Device = nullptr;
SGraphicsPipelineStateDesc m_Desc{};
};
} // namespace Dummy
} // namespace Backend
} // namespace Renderer
#endif // INCLUDED_RENDERER_BACKEND_DUMMY_PIPELINESTATE

View File

@ -26,6 +26,7 @@
#include "ps/ConfigDB.h" #include "ps/ConfigDB.h"
#include "ps/Profile.h" #include "ps/Profile.h"
#include "renderer/backend/gl/DeviceCommandContext.h" #include "renderer/backend/gl/DeviceCommandContext.h"
#include "renderer/backend/gl/PipelineState.h"
#include "renderer/backend/gl/Texture.h" #include "renderer/backend/gl/Texture.h"
#include "scriptinterface/JSON.h" #include "scriptinterface/JSON.h"
#include "scriptinterface/Object.h" #include "scriptinterface/Object.h"
@ -868,6 +869,12 @@ std::unique_ptr<IDeviceCommandContext> CDevice::CreateCommandContext()
return commandContet; return commandContet;
} }
std::unique_ptr<IGraphicsPipelineState> CDevice::CreateGraphicsPipelineState(
const SGraphicsPipelineStateDesc& pipelineStateDesc)
{
return CGraphicsPipelineState::Create(this, pipelineStateDesc);
}
std::unique_ptr<ITexture> CDevice::CreateTexture( std::unique_ptr<ITexture> CDevice::CreateTexture(
const char* name, const ITexture::Type type, const uint32_t usage, const char* name, const ITexture::Type type, const uint32_t usage,
const Format format, const uint32_t width, const uint32_t height, const Format format, const uint32_t width, const uint32_t height,

View File

@ -68,6 +68,9 @@ public:
std::unique_ptr<IDeviceCommandContext> CreateCommandContext() override; std::unique_ptr<IDeviceCommandContext> CreateCommandContext() override;
std::unique_ptr<IGraphicsPipelineState> CreateGraphicsPipelineState(
const SGraphicsPipelineStateDesc& pipelineStateDesc) override;
CDeviceCommandContext* GetActiveCommandContext() { return m_ActiveCommandContext; } CDeviceCommandContext* GetActiveCommandContext() { return m_ActiveCommandContext; }
std::unique_ptr<ITexture> CreateTexture( std::unique_ptr<ITexture> CreateTexture(

View File

@ -24,6 +24,7 @@
#include "renderer/backend/gl/Device.h" #include "renderer/backend/gl/Device.h"
#include "renderer/backend/gl/Framebuffer.h" #include "renderer/backend/gl/Framebuffer.h"
#include "renderer/backend/gl/Mapping.h" #include "renderer/backend/gl/Mapping.h"
#include "renderer/backend/gl/PipelineState.h"
#include "renderer/backend/gl/ShaderProgram.h" #include "renderer/backend/gl/ShaderProgram.h"
#include "renderer/backend/gl/Texture.h" #include "renderer/backend/gl/Texture.h"
@ -43,7 +44,7 @@ namespace GL
namespace namespace
{ {
bool operator==(const StencilOpState& lhs, const StencilOpState& rhs) bool operator==(const SStencilOpState& lhs, const SStencilOpState& rhs)
{ {
return return
lhs.failOp == rhs.failOp && lhs.failOp == rhs.failOp &&
@ -51,7 +52,7 @@ bool operator==(const StencilOpState& lhs, const StencilOpState& rhs)
lhs.depthFailOp == rhs.depthFailOp && lhs.depthFailOp == rhs.depthFailOp &&
lhs.compareOp == rhs.compareOp; lhs.compareOp == rhs.compareOp;
} }
bool operator!=(const StencilOpState& lhs, const StencilOpState& rhs) bool operator!=(const SStencilOpState& lhs, const SStencilOpState& rhs)
{ {
return !operator==(lhs, rhs); return !operator==(lhs, rhs);
} }
@ -259,9 +260,17 @@ IDevice* CDeviceCommandContext::GetDevice()
} }
void CDeviceCommandContext::SetGraphicsPipelineState( void CDeviceCommandContext::SetGraphicsPipelineState(
const GraphicsPipelineStateDesc& pipelineStateDesc) const SGraphicsPipelineStateDesc& pipelineState)
{ {
SetGraphicsPipelineStateImpl(pipelineStateDesc, false); SetGraphicsPipelineStateImpl(pipelineState, false);
}
void CDeviceCommandContext::SetGraphicsPipelineState(
IGraphicsPipelineState* pipelineState)
{
ENSURE(pipelineState);
SetGraphicsPipelineStateImpl(
pipelineState->As<CGraphicsPipelineState>()->GetDesc(), false);
} }
void CDeviceCommandContext::UploadTexture( void CDeviceCommandContext::UploadTexture(
@ -556,7 +565,7 @@ void CDeviceCommandContext::ResetStates()
} }
void CDeviceCommandContext::SetGraphicsPipelineStateImpl( void CDeviceCommandContext::SetGraphicsPipelineStateImpl(
const GraphicsPipelineStateDesc& pipelineStateDesc, const bool force) const SGraphicsPipelineStateDesc& pipelineStateDesc, const bool force)
{ {
ENSURE(!m_InsidePass); ENSURE(!m_InsidePass);
@ -589,8 +598,8 @@ void CDeviceCommandContext::SetGraphicsPipelineStateImpl(
m_ShaderProgram = nextShaderProgram; m_ShaderProgram = nextShaderProgram;
} }
const DepthStencilStateDesc& currentDepthStencilStateDesc = m_GraphicsPipelineStateDesc.depthStencilState; const SDepthStencilStateDesc& currentDepthStencilStateDesc = m_GraphicsPipelineStateDesc.depthStencilState;
const DepthStencilStateDesc& nextDepthStencilStateDesc = pipelineStateDesc.depthStencilState; const SDepthStencilStateDesc& nextDepthStencilStateDesc = pipelineStateDesc.depthStencilState;
if (force || currentDepthStencilStateDesc.depthTestEnabled != nextDepthStencilStateDesc.depthTestEnabled) if (force || currentDepthStencilStateDesc.depthTestEnabled != nextDepthStencilStateDesc.depthTestEnabled)
{ {
if (nextDepthStencilStateDesc.depthTestEnabled) if (nextDepthStencilStateDesc.depthTestEnabled)
@ -675,8 +684,8 @@ void CDeviceCommandContext::SetGraphicsPipelineStateImpl(
} }
} }
const BlendStateDesc& currentBlendStateDesc = m_GraphicsPipelineStateDesc.blendState; const SBlendStateDesc& currentBlendStateDesc = m_GraphicsPipelineStateDesc.blendState;
const BlendStateDesc& nextBlendStateDesc = pipelineStateDesc.blendState; const SBlendStateDesc& nextBlendStateDesc = pipelineStateDesc.blendState;
if (force || currentBlendStateDesc.enabled != nextBlendStateDesc.enabled) if (force || currentBlendStateDesc.enabled != nextBlendStateDesc.enabled)
{ {
if (nextBlendStateDesc.enabled) if (nextBlendStateDesc.enabled)
@ -739,9 +748,9 @@ void CDeviceCommandContext::SetGraphicsPipelineStateImpl(
ApplyColorMask(nextBlendStateDesc.colorWriteMask); ApplyColorMask(nextBlendStateDesc.colorWriteMask);
} }
const RasterizationStateDesc& currentRasterizationStateDesc = const SRasterizationStateDesc& currentRasterizationStateDesc =
m_GraphicsPipelineStateDesc.rasterizationState; m_GraphicsPipelineStateDesc.rasterizationState;
const RasterizationStateDesc& nextRasterizationStateDesc = const SRasterizationStateDesc& nextRasterizationStateDesc =
pipelineStateDesc.rasterizationState; pipelineStateDesc.rasterizationState;
if (force || if (force ||
currentRasterizationStateDesc.polygonMode != nextRasterizationStateDesc.polygonMode) currentRasterizationStateDesc.polygonMode != nextRasterizationStateDesc.polygonMode)
@ -867,6 +876,9 @@ void CDeviceCommandContext::ClearFramebuffer(const bool color, const bool depth,
void CDeviceCommandContext::BeginFramebufferPass(IFramebuffer* framebuffer) void CDeviceCommandContext::BeginFramebufferPass(IFramebuffer* framebuffer)
{ {
SetGraphicsPipelineStateImpl(
MakeDefaultGraphicsPipelineStateDesc(), false);
ENSURE(!m_InsideFramebufferPass); ENSURE(!m_InsideFramebufferPass);
m_InsideFramebufferPass = true; m_InsideFramebufferPass = true;
ENSURE(framebuffer); ENSURE(framebuffer);

View File

@ -53,7 +53,9 @@ public:
IDevice* GetDevice() override; IDevice* GetDevice() override;
void SetGraphicsPipelineState(const GraphicsPipelineStateDesc& pipelineStateDesc) override; void SetGraphicsPipelineState(const SGraphicsPipelineStateDesc& pipelineState);
void SetGraphicsPipelineState(IGraphicsPipelineState* pipelineState) override;
void BlitFramebuffer(IFramebuffer* destinationFramebuffer, IFramebuffer* sourceFramebuffer) override; void BlitFramebuffer(IFramebuffer* destinationFramebuffer, IFramebuffer* sourceFramebuffer) override;
@ -155,14 +157,14 @@ private:
void ResetStates(); void ResetStates();
void SetGraphicsPipelineStateImpl( void SetGraphicsPipelineStateImpl(
const GraphicsPipelineStateDesc& pipelineStateDesc, const bool force); const SGraphicsPipelineStateDesc& pipelineStateDesc, const bool force);
void BindTexture(const uint32_t unit, const GLenum target, const GLuint handle); void BindTexture(const uint32_t unit, const GLenum target, const GLuint handle);
void BindBuffer(const IBuffer::Type type, CBuffer* buffer); void BindBuffer(const IBuffer::Type type, CBuffer* buffer);
CDevice* m_Device = nullptr; CDevice* m_Device = nullptr;
GraphicsPipelineStateDesc m_GraphicsPipelineStateDesc{}; SGraphicsPipelineStateDesc m_GraphicsPipelineStateDesc{};
CFramebuffer* m_Framebuffer = nullptr; CFramebuffer* m_Framebuffer = nullptr;
CShaderProgram* m_ShaderProgram = nullptr; CShaderProgram* m_ShaderProgram = nullptr;
uint32_t m_ScissorCount = 0; uint32_t m_ScissorCount = 0;

View File

@ -0,0 +1,52 @@
/* Copyright (C) 2022 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. 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 2 of the License, or
* (at your option) any later version.
*
* 0 A.D. 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 0 A.D. If not, see <http://www.gnu.org/licenses/>.
*/
#include "precompiled.h"
#include "PipelineState.h"
#include "renderer/backend/gl/Device.h"
namespace Renderer
{
namespace Backend
{
namespace GL
{
// static
std::unique_ptr<CGraphicsPipelineState> CGraphicsPipelineState::Create(
CDevice* device, const SGraphicsPipelineStateDesc& desc)
{
std::unique_ptr<CGraphicsPipelineState> pipelineState{new CGraphicsPipelineState()};
pipelineState->m_Device = device;
pipelineState->m_Desc = desc;
return pipelineState;
}
IDevice* CGraphicsPipelineState::GetDevice()
{
return m_Device;
}
} // namespace GL
} // namespace Backend
} // namespace Renderer

View File

@ -0,0 +1,68 @@
/* Copyright (C) 2022 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. 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 2 of the License, or
* (at your option) any later version.
*
* 0 A.D. 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 0 A.D. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef INCLUDED_RENDERER_BACKEND_GL_PIPELINESTATE
#define INCLUDED_RENDERER_BACKEND_GL_PIPELINESTATE
#include "lib/ogl.h"
#include "renderer/backend/PipelineState.h"
#include <cstdint>
#include <memory>
namespace Renderer
{
namespace Backend
{
namespace GL
{
class CDevice;
class CGraphicsPipelineState final : public IGraphicsPipelineState
{
public:
~CGraphicsPipelineState() override = default;
IDevice* GetDevice() override;
IShaderProgram* GetShaderProgram() const override { return m_Desc.shaderProgram; }
const SGraphicsPipelineStateDesc& GetDesc() const { return m_Desc; }
private:
friend class CDevice;
static std::unique_ptr<CGraphicsPipelineState> Create(
CDevice* device, const SGraphicsPipelineStateDesc& desc);
CGraphicsPipelineState() = default;
CDevice* m_Device = nullptr;
SGraphicsPipelineStateDesc m_Desc{};
};
} // namespace GL
} // namespace Backend
} // namespace Renderer
#endif // INCLUDED_RENDERER_BACKEND_GL_PIPELINESTATE

View File

@ -79,6 +79,13 @@ std::unique_ptr<IDeviceCommandContext> CDevice::CreateCommandContext()
return nullptr; return nullptr;
} }
std::unique_ptr<IGraphicsPipelineState> CDevice::CreateGraphicsPipelineState(
const SGraphicsPipelineStateDesc& pipelineStateDesc)
{
UNUSED2(pipelineStateDesc);
return nullptr;
}
std::unique_ptr<ITexture> CDevice::CreateTexture( std::unique_ptr<ITexture> CDevice::CreateTexture(
const char* name, const ITexture::Type type, const uint32_t usage, const char* name, const ITexture::Type type, const uint32_t usage,
const Format format, const uint32_t width, const uint32_t height, const Format format, const uint32_t width, const uint32_t height,

View File

@ -56,6 +56,9 @@ public:
std::unique_ptr<IDeviceCommandContext> CreateCommandContext() override; std::unique_ptr<IDeviceCommandContext> CreateCommandContext() override;
std::unique_ptr<IGraphicsPipelineState> CreateGraphicsPipelineState(
const SGraphicsPipelineStateDesc& pipelineStateDesc) override;
std::unique_ptr<ITexture> CreateTexture( std::unique_ptr<ITexture> CreateTexture(
const char* name, const ITexture::Type type, const uint32_t usage, const char* name, const ITexture::Type type, const uint32_t usage,
const Format format, const uint32_t width, const uint32_t height, const Format format, const uint32_t width, const uint32_t height,