1
0
forked from 0ad/0ad

Switches from per draw vertex attribute format to precompiled vertex input layout.

Comments By: phosit, Stan
Differential Revision: https://code.wildfiregames.com/D4852
This was SVN commit r27363.
This commit is contained in:
Vladislav Belov 2023-01-06 00:39:25 +00:00
parent 90a3e2b2e7
commit 90f064ff03
50 changed files with 871 additions and 516 deletions

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2022 Wildfire Games.
/* Copyright (C) 2023 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -86,6 +86,15 @@ public:
: WidthInPixels(widthInPixels), HeightInPixels(heightInPixels),
Scale(scale), DeviceCommandContext(deviceCommandContext)
{
constexpr std::array<Renderer::Backend::SVertexAttributeFormat, 2> attributes{{
{Renderer::Backend::VertexAttributeStream::POSITION,
Renderer::Backend::Format::R32G32_SFLOAT, 0, sizeof(float) * 2,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0},
{Renderer::Backend::VertexAttributeStream::UV0,
Renderer::Backend::Format::R32G32_SFLOAT, 0, sizeof(float) * 2,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 1}
}};
m_VertexInputLayout = g_Renderer.GetVertexInputLayout(attributes);
}
void BindTechIfNeeded()
@ -118,14 +127,7 @@ public:
DeviceCommandContext->SetUniform(
BindingSlots.translation, Translation.AsFloatArray());
DeviceCommandContext->SetVertexAttributeFormat(
Renderer::Backend::VertexAttributeStream::POSITION,
Renderer::Backend::Format::R32G32_SFLOAT, 0, sizeof(float) * 2,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0);
DeviceCommandContext->SetVertexAttributeFormat(
Renderer::Backend::VertexAttributeStream::UV0,
Renderer::Backend::Format::R32G32_SFLOAT, 0, sizeof(float) * 2,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 1);
DeviceCommandContext->SetVertexInputLayout(m_VertexInputLayout);
}
void UnbindTech()
@ -163,6 +165,8 @@ public:
CVector2D TransformScale;
CVector2D Translation;
Renderer::Backend::IVertexInputLayout* m_VertexInputLayout = nullptr;
Renderer::Backend::IDeviceCommandContext* DeviceCommandContext = nullptr;
CShaderTechniquePtr Tech;

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2022 Wildfire Games.
/* Copyright (C) 2023 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -91,6 +91,16 @@ bool CLOSTexture::CreateShader()
return false;
}
const std::array<Renderer::Backend::SVertexAttributeFormat, 2> attributes{{
{Renderer::Backend::VertexAttributeStream::POSITION,
Renderer::Backend::Format::R32G32_SFLOAT, 0, sizeof(float) * 2,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0},
{Renderer::Backend::VertexAttributeStream::UV0,
Renderer::Backend::Format::R32G32_SFLOAT, 0, sizeof(float) * 2,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 1}
}};
m_VertexInputLayout = g_Renderer.GetVertexInputLayout(attributes);
return true;
}
@ -186,14 +196,7 @@ void CLOSTexture::InterpolateLOS(Renderer::Backend::IDeviceCommandContext* devic
1.0f, 1.0f
};
deviceCommandContext->SetVertexAttributeFormat(
Renderer::Backend::VertexAttributeStream::POSITION,
Renderer::Backend::Format::R32G32_SFLOAT, 0, sizeof(float) * 2,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0);
deviceCommandContext->SetVertexAttributeFormat(
Renderer::Backend::VertexAttributeStream::UV0,
Renderer::Backend::Format::R32G32_SFLOAT, 0, sizeof(float) * 2,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 1);
deviceCommandContext->SetVertexInputLayout(m_VertexInputLayout);
deviceCommandContext->SetVertexBufferData(
0, quadVerts, std::size(quadVerts) * sizeof(quadVerts[0]));

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2022 Wildfire Games.
/* Copyright (C) 2023 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -23,6 +23,7 @@
#include "renderer/backend/Format.h"
#include "renderer/backend/IDeviceCommandContext.h"
#include "renderer/backend/IFramebuffer.h"
#include "renderer/backend/IShaderProgram.h"
#include "renderer/backend/ITexture.h"
#include <memory>
@ -96,6 +97,7 @@ private:
size_t m_TextureFormatStride = 0;
std::unique_ptr<Renderer::Backend::ITexture>
m_Texture, m_SmoothTextures[2];
Renderer::Backend::IVertexInputLayout* m_VertexInputLayout = nullptr;
uint32_t m_WhichTexture = 0;
double m_LastTextureRecomputeTime = 0.0;

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2022 Wildfire Games.
/* Copyright (C) 2023 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -81,7 +81,8 @@ unsigned int ScaleColor(unsigned int color, float x)
}
void DrawTexture(
Renderer::Backend::IDeviceCommandContext* deviceCommandContext)
Renderer::Backend::IDeviceCommandContext* deviceCommandContext,
Renderer::Backend::IVertexInputLayout* quadVertexInputLayout)
{
const float quadUVs[] =
{
@ -104,14 +105,7 @@ void DrawTexture(
-1.0f, -1.0f,
};
deviceCommandContext->SetVertexAttributeFormat(
Renderer::Backend::VertexAttributeStream::POSITION,
Renderer::Backend::Format::R32G32_SFLOAT, 0, sizeof(float) * 2,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0);
deviceCommandContext->SetVertexAttributeFormat(
Renderer::Backend::VertexAttributeStream::UV0,
Renderer::Backend::Format::R32G32_SFLOAT, 0, sizeof(float) * 2,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 1);
deviceCommandContext->SetVertexInputLayout(quadVertexInputLayout);
deviceCommandContext->SetVertexBufferData(
0, quadVertices, std::size(quadVertices) * sizeof(quadVertices[0]));
@ -247,6 +241,17 @@ CMiniMapTexture::CMiniMapTexture(CSimulation2& simulation)
}
m_VertexArray.Upload();
const std::array<Renderer::Backend::SVertexAttributeFormat, 2> attributes{{
{Renderer::Backend::VertexAttributeStream::POSITION,
Renderer::Backend::Format::R32G32_SFLOAT, 0, sizeof(float) * 2,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0},
{Renderer::Backend::VertexAttributeStream::UV0,
Renderer::Backend::Format::R32G32_SFLOAT, 0, sizeof(float) * 2,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 1}
}};
m_QuadVertexInputLayout = g_Renderer.GetVertexInputLayout(attributes);
const uint32_t stride = m_VertexArray.GetStride();
if (g_VideoMode.GetBackendDevice()->GetCapabilities().instancing)
{
m_UseInstancing = true;
@ -281,6 +286,32 @@ CMiniMapTexture::CMiniMapTexture(CSimulation2& simulation)
m_InstanceVertexArray.Upload();
m_InstanceVertexArray.FreeBackingStore();
const std::array<Renderer::Backend::SVertexAttributeFormat, 3> attributes{{
{Renderer::Backend::VertexAttributeStream::POSITION,
m_InstanceAttributePosition.format, m_InstanceAttributePosition.offset,
m_InstanceVertexArray.GetStride(),
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0},
{Renderer::Backend::VertexAttributeStream::UV1,
m_AttributePos.format, m_AttributePos.offset, stride,
Renderer::Backend::VertexAttributeRate::PER_INSTANCE, 1},
{Renderer::Backend::VertexAttributeStream::COLOR,
m_AttributeColor.format, m_AttributeColor.offset, stride,
Renderer::Backend::VertexAttributeRate::PER_INSTANCE, 1},
}};
m_EntitiesVertexInputLayout = g_Renderer.GetVertexInputLayout(attributes);
}
else
{
const std::array<Renderer::Backend::SVertexAttributeFormat, 2> entitiesAttributes{{
{Renderer::Backend::VertexAttributeStream::POSITION,
m_AttributePos.format, m_AttributePos.offset, stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0},
{Renderer::Backend::VertexAttributeStream::COLOR,
m_AttributeColor.format, m_AttributeColor.offset, stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0}
}};
m_EntitiesVertexInputLayout = g_Renderer.GetVertexInputLayout(entitiesAttributes);
}
CShaderDefines baseDefines;
@ -530,7 +561,7 @@ void CMiniMapTexture::RenderFinalTexture(
baseTransform._14, baseTransform._24, terrainTransform._14, terrainTransform._24);
if (m_TerrainTexture)
DrawTexture(deviceCommandContext);
DrawTexture(deviceCommandContext, m_QuadVertexInputLayout);
deviceCommandContext->EndPass();
deviceCommandContext->SetGraphicsPipelineState(
@ -552,7 +583,7 @@ void CMiniMapTexture::RenderFinalTexture(
shader->GetBindingSlot(str_translation),
baseTransform._14, baseTransform._24, territoryTransform._14, territoryTransform._24);
DrawTexture(deviceCommandContext);
DrawTexture(deviceCommandContext, m_QuadVertexInputLayout);
deviceCommandContext->EndPass();
tech = g_Renderer.GetShaderManager().LoadEffect(str_minimap_los, CShaderDefines());
@ -574,7 +605,7 @@ void CMiniMapTexture::RenderFinalTexture(
shader->GetBindingSlot(str_translation),
baseTransform._14, baseTransform._24, losTransform._14, losTransform._24);
DrawTexture(deviceCommandContext);
DrawTexture(deviceCommandContext, m_QuadVertexInputLayout);
deviceCommandContext->EndPass();
@ -800,23 +831,9 @@ void CMiniMapTexture::DrawEntities(
const uint32_t stride = m_VertexArray.GetStride();
const uint32_t firstVertexOffset = m_VertexArray.GetOffset() * stride;
deviceCommandContext->SetVertexInputLayout(m_EntitiesVertexInputLayout);
if (m_UseInstancing)
{
deviceCommandContext->SetVertexAttributeFormat(
Renderer::Backend::VertexAttributeStream::POSITION,
m_InstanceAttributePosition.format, m_InstanceAttributePosition.offset,
m_InstanceVertexArray.GetStride(),
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0);
deviceCommandContext->SetVertexAttributeFormat(
Renderer::Backend::VertexAttributeStream::UV1,
m_AttributePos.format, m_AttributePos.offset, stride,
Renderer::Backend::VertexAttributeRate::PER_INSTANCE, 1);
deviceCommandContext->SetVertexAttributeFormat(
Renderer::Backend::VertexAttributeStream::COLOR,
m_AttributeColor.format, m_AttributeColor.offset, stride,
Renderer::Backend::VertexAttributeRate::PER_INSTANCE, 1);
deviceCommandContext->SetVertexBuffer(
0, m_InstanceVertexArray.GetBuffer(), m_InstanceVertexArray.GetOffset());
deviceCommandContext->SetVertexBuffer(
@ -828,15 +845,6 @@ void CMiniMapTexture::DrawEntities(
}
else
{
deviceCommandContext->SetVertexAttributeFormat(
Renderer::Backend::VertexAttributeStream::POSITION,
m_AttributePos.format, m_AttributePos.offset, stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0);
deviceCommandContext->SetVertexAttributeFormat(
Renderer::Backend::VertexAttributeStream::COLOR,
m_AttributeColor.format, m_AttributeColor.offset, stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0);
deviceCommandContext->SetVertexBuffer(
0, m_VertexArray.GetBuffer(), firstVertexOffset);
deviceCommandContext->SetIndexBuffer(m_IndexArray.GetBuffer());

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2022 Wildfire Games.
/* Copyright (C) 2023 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -23,6 +23,7 @@
#include "graphics/Texture.h"
#include "maths/Vector2D.h"
#include "renderer/backend/IDeviceCommandContext.h"
#include "renderer/backend/IShaderProgram.h"
#include "renderer/backend/ITexture.h"
#include "renderer/VertexArray.h"
@ -114,6 +115,9 @@ private:
float m_ShallowPassageHeight = 0.0f;
float m_WaterHeight = 0.0f;
Renderer::Backend::IVertexInputLayout* m_QuadVertexInputLayout = nullptr;
Renderer::Backend::IVertexInputLayout* m_EntitiesVertexInputLayout = nullptr;
VertexIndexArray m_IndexArray;
VertexArray m_VertexArray;
VertexArray::Attribute m_AttributePos;

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2022 Wildfire Games.
/* Copyright (C) 2023 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -77,6 +77,23 @@ CParticleEmitter::CParticleEmitter(const CParticleEmitterTypePtr& type) :
}
m_IndexArray.Upload();
m_IndexArray.FreeBackingStore();
const uint32_t stride = m_VertexArray.GetStride();
const std::array<Renderer::Backend::SVertexAttributeFormat, 4> attributes{{
{Renderer::Backend::VertexAttributeStream::POSITION,
m_AttributePos.format, m_AttributePos.offset, stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0},
{Renderer::Backend::VertexAttributeStream::COLOR,
m_AttributeColor.format, m_AttributeColor.offset, stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0},
{Renderer::Backend::VertexAttributeStream::UV0,
m_AttributeUV.format, m_AttributeUV.offset, stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0},
{Renderer::Backend::VertexAttributeStream::UV1,
m_AttributeAxis.format, m_AttributeAxis.offset, stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0},
}};
m_VertexInputLayout = g_Renderer.GetVertexInputLayout(attributes);
}
void CParticleEmitter::UpdateArrayData(int frameNumber)
@ -215,22 +232,7 @@ void CParticleEmitter::RenderArray(
const uint32_t stride = m_VertexArray.GetStride();
const uint32_t firstVertexOffset = m_VertexArray.GetOffset() * stride;
deviceCommandContext->SetVertexAttributeFormat(
Renderer::Backend::VertexAttributeStream::POSITION,
m_AttributePos.format, m_AttributePos.offset, stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0);
deviceCommandContext->SetVertexAttributeFormat(
Renderer::Backend::VertexAttributeStream::COLOR,
m_AttributeColor.format, m_AttributeColor.offset, stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0);
deviceCommandContext->SetVertexAttributeFormat(
Renderer::Backend::VertexAttributeStream::UV0,
m_AttributeUV.format, m_AttributeUV.offset, stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0);
deviceCommandContext->SetVertexAttributeFormat(
Renderer::Backend::VertexAttributeStream::UV1,
m_AttributeAxis.format, m_AttributeAxis.offset, stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0);
deviceCommandContext->SetVertexInputLayout(m_VertexInputLayout);
deviceCommandContext->SetVertexBuffer(
0, m_VertexArray.GetBuffer(), firstVertexOffset);

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2022 Wildfire Games.
/* Copyright (C) 2023 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -177,6 +177,8 @@ private:
VertexArray::Attribute m_AttributeUV;
VertexArray::Attribute m_AttributeColor;
Renderer::Backend::IVertexInputLayout* m_VertexInputLayout = nullptr;
int m_LastFrameNumber;
};

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2022 Wildfire Games.
/* Copyright (C) 2023 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -35,6 +35,16 @@
#include <cmath>
void CDebugRenderer::Initialize()
{
const std::array<Renderer::Backend::SVertexAttributeFormat, 1> attributes{{
{Renderer::Backend::VertexAttributeStream::POSITION,
Renderer::Backend::Format::R32G32B32_SFLOAT, 0, sizeof(float) * 3,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0}
}};
m_VertexInputLayout = g_Renderer.GetVertexInputLayout(attributes);
}
void CDebugRenderer::DrawLine(
const CVector3D& from, const CVector3D& to, const CColor& color,
const float width, const bool depthTestEnabled)
@ -99,10 +109,7 @@ void CDebugRenderer::DrawLine(
#undef ADD
deviceCommandContext->SetVertexAttributeFormat(
Renderer::Backend::VertexAttributeStream::POSITION,
Renderer::Backend::Format::R32G32B32_SFLOAT, 0, sizeof(float) * 3,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0);
deviceCommandContext->SetVertexInputLayout(m_VertexInputLayout);
deviceCommandContext->SetVertexBufferData(
0, vertices.data(), vertices.size() * sizeof(vertices[0]));
@ -156,10 +163,7 @@ void CDebugRenderer::DrawCircle(const CVector3D& origin, const float radius, con
#undef ADD
deviceCommandContext->SetVertexAttributeFormat(
Renderer::Backend::VertexAttributeStream::POSITION,
Renderer::Backend::Format::R32G32B32_SFLOAT, 0, sizeof(float) * 3,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0);
deviceCommandContext->SetVertexInputLayout(m_VertexInputLayout);
deviceCommandContext->SetVertexBufferData(
0, vertices.data(), vertices.size() * sizeof(vertices[0]));
@ -237,10 +241,7 @@ void CDebugRenderer::DrawCameraFrustum(const CCamera& camera, const CColor& colo
ADD(intermediatePoints[3]);
}
deviceCommandContext->SetVertexAttributeFormat(
Renderer::Backend::VertexAttributeStream::POSITION,
Renderer::Backend::Format::R32G32B32_SFLOAT, 0, sizeof(float) * 3,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0);
deviceCommandContext->SetVertexInputLayout(m_VertexInputLayout);
deviceCommandContext->SetVertexBufferData(
0, vertices.data(), vertices.size() * sizeof(vertices[0]));
@ -260,10 +261,7 @@ void CDebugRenderer::DrawCameraFrustum(const CCamera& camera, const CColor& colo
ADD(farPoints[nextI]);
}
deviceCommandContext->SetVertexAttributeFormat(
Renderer::Backend::VertexAttributeStream::POSITION,
Renderer::Backend::Format::R32G32B32_SFLOAT, 0, sizeof(float) * 3,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0);
deviceCommandContext->SetVertexInputLayout(m_VertexInputLayout);
deviceCommandContext->SetVertexBufferData(
0, vertices.data(), vertices.size() * sizeof(vertices[0]));
@ -323,10 +321,7 @@ void CDebugRenderer::DrawBoundingBox(
#undef ADD_FACE
deviceCommandContext->SetVertexAttributeFormat(
Renderer::Backend::VertexAttributeStream::POSITION,
Renderer::Backend::Format::R32G32B32_SFLOAT, 0, sizeof(float) * 3,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0);
deviceCommandContext->SetVertexInputLayout(m_VertexInputLayout);
deviceCommandContext->SetVertexBufferData(
0, data.data(), data.size() * sizeof(data[0]));
@ -379,10 +374,7 @@ void CDebugRenderer::DrawBrush(const CBrush& brush, const CColor& color, bool wi
#undef ADD_VERT
deviceCommandContext->SetVertexAttributeFormat(
Renderer::Backend::VertexAttributeStream::POSITION,
Renderer::Backend::Format::R32G32B32_SFLOAT, 0, sizeof(float) * 3,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0);
deviceCommandContext->SetVertexInputLayout(m_VertexInputLayout);
deviceCommandContext->SetVertexBufferData(
0, data.data(), data.size() * sizeof(data[0]));

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2022 Wildfire Games.
/* Copyright (C) 2023 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -20,6 +20,7 @@
#include "graphics/ShaderTechniquePtr.h"
#include "ps/CStrIntern.h"
#include "renderer/backend/IShaderProgram.h"
#include <unordered_map>
#include <vector>
@ -37,6 +38,8 @@ struct CColor;
class CDebugRenderer
{
public:
void Initialize();
/**
* Render the line in world space.
*/
@ -91,6 +94,8 @@ private:
};
std::unordered_map<ShaderTechniqueKey, CShaderTechniquePtr, ShaderTechniqueKeyHash, ShaderTechniqueKeyEqual>
m_ShaderTechniqueMapping;
Renderer::Backend::IVertexInputLayout* m_VertexInputLayout = nullptr;
};
#endif // INCLUDED_DEBUGRENDERER

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2022 Wildfire Games.
/* Copyright (C) 2023 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -76,6 +76,27 @@ struct SDecalBatchComparator
} // anonymous namespace
// static
Renderer::Backend::IVertexInputLayout* CDecalRData::GetVertexInputLayout()
{
const uint32_t stride = sizeof(SDecalVertex);
const std::array<Renderer::Backend::SVertexAttributeFormat, 3> attributes{{
{Renderer::Backend::VertexAttributeStream::POSITION,
Renderer::Backend::Format::R32G32B32_SFLOAT,
offsetof(SDecalVertex, m_Position), stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0},
{Renderer::Backend::VertexAttributeStream::NORMAL,
Renderer::Backend::Format::R32G32B32_SFLOAT,
offsetof(SDecalVertex, m_Normal), stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0},
{Renderer::Backend::VertexAttributeStream::UV0,
Renderer::Backend::Format::R32G32_SFLOAT,
offsetof(SDecalVertex, m_UV), stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0}
}};
return g_Renderer.GetVertexInputLayout(attributes);
}
CDecalRData::CDecalRData(CModelDecal* decal, CSimulation2* simulation)
: m_Decal(decal), m_Simulation(simulation)
{
@ -96,6 +117,7 @@ void CDecalRData::Update(CSimulation2* simulation)
void CDecalRData::RenderDecals(
Renderer::Backend::IDeviceCommandContext* deviceCommandContext,
Renderer::Backend::IVertexInputLayout* vertexInputLayout,
const std::vector<CDecalRData*>& decals, const CShaderDefines& context, ShadowMap* shadow)
{
PROFILE3("render terrain decals");
@ -224,23 +246,7 @@ void CDecalRData::RenderDecals(
lastVB = batch.vertices->m_Owner;
ENSURE(!lastVB->GetBuffer()->IsDynamic());
const uint32_t stride = sizeof(SDecalVertex);
deviceCommandContext->SetVertexAttributeFormat(
Renderer::Backend::VertexAttributeStream::POSITION,
Renderer::Backend::Format::R32G32B32_SFLOAT,
offsetof(SDecalVertex, m_Position), stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0);
deviceCommandContext->SetVertexAttributeFormat(
Renderer::Backend::VertexAttributeStream::NORMAL,
Renderer::Backend::Format::R32G32B32_SFLOAT,
offsetof(SDecalVertex, m_Normal), stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0);
deviceCommandContext->SetVertexAttributeFormat(
Renderer::Backend::VertexAttributeStream::UV0,
Renderer::Backend::Format::R32G32_SFLOAT,
offsetof(SDecalVertex, m_UV), stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0);
deviceCommandContext->SetVertexInputLayout(vertexInputLayout);
deviceCommandContext->SetVertexBuffer(
0, batch.vertices->m_Owner->GetBuffer(), 0);

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2022 Wildfire Games.
/* Copyright (C) 2023 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -22,6 +22,7 @@
#include "maths/Vector2D.h"
#include "maths/Vector3D.h"
#include "renderer/backend/IDeviceCommandContext.h"
#include "renderer/backend/IShaderProgram.h"
#include "renderer/VertexBufferManager.h"
#include <vector>
@ -37,10 +38,13 @@ public:
CDecalRData(CModelDecal* decal, CSimulation2* simulation);
~CDecalRData();
static Renderer::Backend::IVertexInputLayout* GetVertexInputLayout();
void Update(CSimulation2* simulation);
static void RenderDecals(
Renderer::Backend::IDeviceCommandContext* deviceCommandContext,
Renderer::Backend::IVertexInputLayout* vertexInputLayout,
const std::vector<CDecalRData*>& decals, const CShaderDefines& context, ShadowMap* shadow);
CModelDecal* GetDecal() { return m_Decal; }

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2022 Wildfire Games.
/* Copyright (C) 2023 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -27,10 +27,19 @@
#include "lib/bits.h"
#include "lib/sysdep/rtl.h"
#include "maths/Vector3D.h"
#include "ps/containers/StaticVector.h"
#include "renderer/Renderer.h"
#include "renderer/RenderModifiers.h"
#include "renderer/VertexArray.h"
namespace
{
constexpr uint32_t MODEL_VERTEX_ATTRIBUTE_STRIDE = 32;
constexpr uint32_t MODEL_VERTEX_ATTRIBUTE_POSITION_OFFSET = 16;
constexpr uint32_t MODEL_VERTEX_ATTRIBUTE_NORMAL_OFFSET = 0;
} // anonymous namespace
struct ShaderModelDef : public CModelDefRPrivate
{
@ -43,6 +52,8 @@ struct ShaderModelDef : public CModelDefRPrivate
/// The number of UVs is determined by the model
std::vector<VertexArray::Attribute> m_UVs;
Renderer::Backend::IVertexInputLayout* m_VertexInputLayout = nullptr;
ShaderModelDef(const CModelDefPtr& mdef);
};
@ -77,6 +88,31 @@ ShaderModelDef::ShaderModelDef(const CModelDefPtr& mdef)
ModelRenderer::BuildIndices(mdef, m_IndexArray.GetIterator());
m_IndexArray.Upload();
m_IndexArray.FreeBackingStore();
const uint32_t stride = m_Array.GetStride();
PS::StaticVector<Renderer::Backend::SVertexAttributeFormat, 4> attributes{
{Renderer::Backend::VertexAttributeStream::UV0,
m_UVs[0].format, m_UVs[0].offset, stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0},
{Renderer::Backend::VertexAttributeStream::POSITION,
Renderer::Backend::Format::R32G32B32_SFLOAT,
MODEL_VERTEX_ATTRIBUTE_POSITION_OFFSET, MODEL_VERTEX_ATTRIBUTE_STRIDE,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 1},
{Renderer::Backend::VertexAttributeStream::NORMAL,
Renderer::Backend::Format::R32G32B32_SFLOAT,
MODEL_VERTEX_ATTRIBUTE_NORMAL_OFFSET, MODEL_VERTEX_ATTRIBUTE_STRIDE,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 1}
};
if (mdef->GetNumUVsPerVertex() >= 2)
{
attributes.push_back({
Renderer::Backend::VertexAttributeStream::UV1,
m_UVs[1].format, m_UVs[1].offset, stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0});
}
m_VertexInputLayout = g_Renderer.GetVertexInputLayout({attributes.begin(), attributes.end()});
}
@ -147,6 +183,13 @@ CModelRData* ShaderModelVertexRenderer::CreateModelData(const void* key, CModel*
ENSURE(shadermodel->m_Normal.offset % 16 == 0);
ENSURE(shadermodel->m_Array.GetStride() % 16 == 0);
// We assume that the vertex input layout is the same for all models with the
// same ShaderModelDef.
// TODO: we need a more strict way to guarantee that.
ENSURE(shadermodel->m_Array.GetStride() == MODEL_VERTEX_ATTRIBUTE_STRIDE);
ENSURE(shadermodel->m_Position.offset == MODEL_VERTEX_ATTRIBUTE_POSITION_OFFSET);
ENSURE(shadermodel->m_Normal.offset == MODEL_VERTEX_ATTRIBUTE_NORMAL_OFFSET);
return shadermodel;
}
@ -195,23 +238,11 @@ void ShaderModelVertexRenderer::PrepareModelDef(
ENSURE(m->shadermodeldef);
deviceCommandContext->SetVertexInputLayout(m->shadermodeldef->m_VertexInputLayout);
const uint32_t stride = m->shadermodeldef->m_Array.GetStride();
const uint32_t firstVertexOffset = m->shadermodeldef->m_Array.GetOffset() * stride;
deviceCommandContext->SetVertexAttributeFormat(
Renderer::Backend::VertexAttributeStream::UV0,
m->shadermodeldef->m_UVs[0].format,
m->shadermodeldef->m_UVs[0].offset, stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0);
if (def.GetNumUVsPerVertex() >= 2)
{
deviceCommandContext->SetVertexAttributeFormat(
Renderer::Backend::VertexAttributeStream::UV1,
m->shadermodeldef->m_UVs[1].format,
m->shadermodeldef->m_UVs[1].offset, stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0);
}
deviceCommandContext->SetVertexBuffer(
0, m->shadermodeldef->m_Array.GetBuffer(), firstVertexOffset);
}
@ -227,17 +258,6 @@ void ShaderModelVertexRenderer::RenderModel(
const uint32_t stride = shadermodel->m_Array.GetStride();
const uint32_t firstVertexOffset = shadermodel->m_Array.GetOffset() * stride;
deviceCommandContext->SetVertexAttributeFormat(
Renderer::Backend::VertexAttributeStream::POSITION,
Renderer::Backend::Format::R32G32B32_SFLOAT,
shadermodel->m_Position.offset, stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 1);
deviceCommandContext->SetVertexAttributeFormat(
Renderer::Backend::VertexAttributeStream::NORMAL,
Renderer::Backend::Format::R32G32B32_SFLOAT,
shadermodel->m_Normal.offset, stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 1);
deviceCommandContext->SetVertexBuffer(
1, shadermodel->m_Array.GetBuffer(), firstVertexOffset);
deviceCommandContext->SetIndexBuffer(m->shadermodeldef->m_IndexArray.GetBuffer());

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2022 Wildfire Games.
/* Copyright (C) 2023 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -25,6 +25,7 @@
#include "maths/Vector3D.h"
#include "maths/Vector4D.h"
#include "ps/CLogger.h"
#include "ps/containers/StaticVector.h"
#include "ps/CStrInternStatic.h"
#include "renderer/Renderer.h"
#include "renderer/RenderModifiers.h"
@ -47,6 +48,8 @@ struct IModelDef : public CModelDefRPrivate
/// The number of UVs is determined by the model
std::vector<VertexArray::Attribute> m_UVs;
Renderer::Backend::IVertexInputLayout* m_VertexInputLayout = nullptr;
/// Indices are the same for all models, so share them
VertexIndexArray m_IndexArray;
@ -234,8 +237,52 @@ IModelDef::IModelDef(const CModelDefPtr& mdef, bool gpuSkinning, bool calculateT
m_IndexArray.Upload();
m_IndexArray.FreeBackingStore();
}
}
const uint32_t stride = m_Array.GetStride();
constexpr size_t MAX_UV = 2;
PS::StaticVector<Renderer::Backend::SVertexAttributeFormat, 5 + MAX_UV> attributes{
{Renderer::Backend::VertexAttributeStream::POSITION,
m_Position.format, m_Position.offset, stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0},
{Renderer::Backend::VertexAttributeStream::NORMAL,
m_Normal.format, m_Normal.offset, stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0}
};
for (size_t uv = 0; uv < std::min(MAX_UV, mdef->GetNumUVsPerVertex()); ++uv)
{
const Renderer::Backend::VertexAttributeStream stream =
static_cast<Renderer::Backend::VertexAttributeStream>(
static_cast<int>(Renderer::Backend::VertexAttributeStream::UV0) + uv);
attributes.push_back({
stream, m_UVs[uv].format, m_UVs[uv].offset, stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0});
}
// GPU skinning requires extra attributes to compute positions/normals.
if (gpuSkinning)
{
attributes.push_back({
Renderer::Backend::VertexAttributeStream::UV2,
m_BlendJoints.format, m_BlendJoints.offset, stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0});
attributes.push_back({
Renderer::Backend::VertexAttributeStream::UV3,
m_BlendWeights.format, m_BlendWeights.offset, stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0});
}
if (calculateTangents)
{
attributes.push_back({
Renderer::Backend::VertexAttributeStream::UV4,
m_Tangent.format, m_Tangent.offset, stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0});
}
m_VertexInputLayout = g_Renderer.GetVertexInputLayout({attributes.begin(), attributes.end()});
}
struct InstancingModelRendererInternals
{
@ -307,58 +354,13 @@ void InstancingModelRenderer::PrepareModelDef(
m->imodeldef = (IModelDef*)def.GetRenderData(m);
ENSURE(m->imodeldef);
deviceCommandContext->SetVertexInputLayout(m->imodeldef->m_VertexInputLayout);
deviceCommandContext->SetIndexBuffer(m->imodeldef->m_IndexArray.GetBuffer());
const uint32_t stride = m->imodeldef->m_Array.GetStride();
const uint32_t firstVertexOffset = m->imodeldef->m_Array.GetOffset() * stride;
deviceCommandContext->SetVertexAttributeFormat(
Renderer::Backend::VertexAttributeStream::POSITION,
m->imodeldef->m_Position.format,
m->imodeldef->m_Position.offset, stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0);
deviceCommandContext->SetVertexAttributeFormat(
Renderer::Backend::VertexAttributeStream::NORMAL,
m->imodeldef->m_Normal.format,
m->imodeldef->m_Normal.offset, stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0);
constexpr size_t MAX_UV = 2;
for (size_t uv = 0; uv < std::min(MAX_UV, def.GetNumUVsPerVertex()); ++uv)
{
const Renderer::Backend::VertexAttributeStream stream =
static_cast<Renderer::Backend::VertexAttributeStream>(
static_cast<int>(Renderer::Backend::VertexAttributeStream::UV0) + uv);
deviceCommandContext->SetVertexAttributeFormat(
stream, m->imodeldef->m_UVs[uv].format,
m->imodeldef->m_UVs[uv].offset, stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0);
}
// GPU skinning requires extra attributes to compute positions/normals.
if (m->gpuSkinning)
{
deviceCommandContext->SetVertexAttributeFormat(
Renderer::Backend::VertexAttributeStream::UV2,
m->imodeldef->m_BlendJoints.format,
m->imodeldef->m_BlendJoints.offset, stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0);
deviceCommandContext->SetVertexAttributeFormat(
Renderer::Backend::VertexAttributeStream::UV3,
m->imodeldef->m_BlendWeights.format,
m->imodeldef->m_BlendWeights.offset, stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0);
}
if (m->calculateTangents)
{
deviceCommandContext->SetVertexAttributeFormat(
Renderer::Backend::VertexAttributeStream::UV4,
m->imodeldef->m_Tangent.format,
m->imodeldef->m_Tangent.offset, stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0);
}
deviceCommandContext->SetVertexBuffer(
0, m->imodeldef->m_Array.GetBuffer(), firstVertexOffset);
}

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2022 Wildfire Games.
/* Copyright (C) 2023 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -188,6 +188,12 @@ struct OverlayRendererInternals
Shader shaderForegroundOverlay;
Shader shaderOverlaySolid;
Renderer::Backend::IVertexInputLayout* quadVertexInputLayout = nullptr;
Renderer::Backend::IVertexInputLayout* foregroundVertexInputLayout = nullptr;
Renderer::Backend::IVertexInputLayout* sphereVertexInputLayout = nullptr;
Renderer::Backend::IVertexInputLayout* texturedLineVertexInputLayout = nullptr;
// Geometry for a unit sphere
std::vector<float> sphereVertexes;
std::vector<u16> sphereIndexes;
@ -262,6 +268,39 @@ void OverlayRendererInternals::Initialize()
CreateShader(str_foreground_overlay, {});
shaderOverlaySolid =
CreateShader(str_overlay_solid, {});
const uint32_t quadStride = quadVertices.GetStride();
const std::array<Renderer::Backend::SVertexAttributeFormat, 3> quadAttributes{{
{Renderer::Backend::VertexAttributeStream::POSITION,
quadAttributePos.format, quadAttributePos.offset, quadStride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0},
{Renderer::Backend::VertexAttributeStream::COLOR,
quadAttributeColor.format, quadAttributeColor.offset, quadStride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0},
{Renderer::Backend::VertexAttributeStream::UV0,
quadAttributeUV.format, quadAttributeUV.offset, quadStride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0}
}};
quadVertexInputLayout = g_Renderer.GetVertexInputLayout(quadAttributes);
const std::array<Renderer::Backend::SVertexAttributeFormat, 2> foregroundAttributes{{
{Renderer::Backend::VertexAttributeStream::POSITION,
Renderer::Backend::Format::R32G32B32_SFLOAT, 0, sizeof(float) * 3,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0},
{Renderer::Backend::VertexAttributeStream::UV0,
Renderer::Backend::Format::R32G32_SFLOAT, 0, sizeof(float) * 2,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 1}
}};
foregroundVertexInputLayout = g_Renderer.GetVertexInputLayout(foregroundAttributes);
const std::array<Renderer::Backend::SVertexAttributeFormat, 1> shpereAttributes{{
{Renderer::Backend::VertexAttributeStream::POSITION,
Renderer::Backend::Format::R32G32B32_SFLOAT, 0, sizeof(float) * 3,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0}
}};
sphereVertexInputLayout = g_Renderer.GetVertexInputLayout(shpereAttributes);
texturedLineVertexInputLayout = CTexturedLineRData::GetVertexInputLayout();
}
OverlayRenderer::OverlayRenderer()
@ -535,7 +574,8 @@ void OverlayRenderer::RenderTexturedOverlayLines(
continue;
ENSURE(line->m_RenderData);
line->m_RenderData->Render(deviceCommandContext, *line, shader);
line->m_RenderData->Render(
deviceCommandContext, m->texturedLineVertexInputLayout, *line, shader);
}
}
@ -571,18 +611,7 @@ void OverlayRenderer::RenderQuadOverlays(
const uint32_t vertexStride = m->quadVertices.GetStride();
const uint32_t firstVertexOffset = m->quadVertices.GetOffset() * vertexStride;
deviceCommandContext->SetVertexAttributeFormat(
Renderer::Backend::VertexAttributeStream::POSITION,
m->quadAttributePos.format, m->quadAttributePos.offset, vertexStride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0);
deviceCommandContext->SetVertexAttributeFormat(
Renderer::Backend::VertexAttributeStream::COLOR,
m->quadAttributeColor.format, m->quadAttributeColor.offset, vertexStride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0);
deviceCommandContext->SetVertexAttributeFormat(
Renderer::Backend::VertexAttributeStream::UV0,
m->quadAttributeUV.format, m->quadAttributeUV.offset, vertexStride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0);
deviceCommandContext->SetVertexInputLayout(m->quadVertexInputLayout);
deviceCommandContext->SetVertexBuffer(
0, m->quadVertices.GetBuffer(), firstVertexOffset);
@ -650,14 +679,7 @@ void OverlayRenderer::RenderForegroundOverlays(
{0.0f, 0.0f},
};
deviceCommandContext->SetVertexAttributeFormat(
Renderer::Backend::VertexAttributeStream::POSITION,
Renderer::Backend::Format::R32G32B32_SFLOAT, 0, sizeof(float) * 3,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0);
deviceCommandContext->SetVertexAttributeFormat(
Renderer::Backend::VertexAttributeStream::UV0,
Renderer::Backend::Format::R32G32_SFLOAT, 0, sizeof(float) * 2,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 1);
deviceCommandContext->SetVertexInputLayout(m->foregroundVertexInputLayout);
deviceCommandContext->SetVertexBufferData(
1, &uvs[0], std::size(uvs) * sizeof(uvs[0]));
@ -783,10 +805,7 @@ void OverlayRenderer::RenderSphereOverlays(
m->GenerateSphere();
deviceCommandContext->SetVertexAttributeFormat(
Renderer::Backend::VertexAttributeStream::POSITION,
Renderer::Backend::Format::R32G32B32_SFLOAT, 0, 0,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0);
deviceCommandContext->SetVertexInputLayout(m->sphereVertexInputLayout);
deviceCommandContext->SetVertexBufferData(
0, m->sphereVertexes.data(), m->sphereVertexes.size() * sizeof(m->sphereVertexes[0]));

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2022 Wildfire Games.
/* Copyright (C) 2023 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -64,6 +64,145 @@ const ssize_t BlendOffsets[9][2] = {
{ 0, 0 }
};
// static
Renderer::Backend::IVertexInputLayout* CPatchRData::GetBaseVertexInputLayout()
{
const uint32_t stride = sizeof(SBaseVertex);
const std::array<Renderer::Backend::SVertexAttributeFormat, 3> attributes{{
{Renderer::Backend::VertexAttributeStream::POSITION,
Renderer::Backend::Format::R32G32B32_SFLOAT,
offsetof(SBaseVertex, m_Position), stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0},
{Renderer::Backend::VertexAttributeStream::NORMAL,
Renderer::Backend::Format::R32G32B32_SFLOAT,
offsetof(SBaseVertex, m_Normal), stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0},
{Renderer::Backend::VertexAttributeStream::UV0,
Renderer::Backend::Format::R32G32B32_SFLOAT,
offsetof(SBaseVertex, m_Position), stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0}
}};
return g_Renderer.GetVertexInputLayout(attributes);
}
// static
Renderer::Backend::IVertexInputLayout* CPatchRData::GetBlendVertexInputLayout()
{
const uint32_t stride = sizeof(SBlendVertex);
const std::array<Renderer::Backend::SVertexAttributeFormat, 4> attributes{{
{Renderer::Backend::VertexAttributeStream::POSITION,
Renderer::Backend::Format::R32G32B32_SFLOAT,
offsetof(SBlendVertex, m_Position), stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0},
{Renderer::Backend::VertexAttributeStream::NORMAL,
Renderer::Backend::Format::R32G32B32_SFLOAT,
offsetof(SBlendVertex, m_Normal), stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0},
{Renderer::Backend::VertexAttributeStream::UV0,
Renderer::Backend::Format::R32G32B32_SFLOAT,
offsetof(SBlendVertex, m_Position), stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0},
{Renderer::Backend::VertexAttributeStream::UV1,
Renderer::Backend::Format::R32G32_SFLOAT,
offsetof(SBlendVertex, m_AlphaUVs), stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0}
}};
return g_Renderer.GetVertexInputLayout(attributes);
}
// static
Renderer::Backend::IVertexInputLayout* CPatchRData::GetStreamVertexInputLayout(
const bool bindPositionAsTexCoord)
{
const uint32_t stride = sizeof(SBaseVertex);
if (bindPositionAsTexCoord)
{
const std::array<Renderer::Backend::SVertexAttributeFormat, 2> attributes{{
{Renderer::Backend::VertexAttributeStream::POSITION,
Renderer::Backend::Format::R32G32B32_SFLOAT,
offsetof(SBaseVertex, m_Position), stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0},
{Renderer::Backend::VertexAttributeStream::UV0,
Renderer::Backend::Format::R32G32B32_SFLOAT,
offsetof(SBaseVertex, m_Position), stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0}
}};
return g_Renderer.GetVertexInputLayout(attributes);
}
else
{
const std::array<Renderer::Backend::SVertexAttributeFormat, 1> attributes{{
{Renderer::Backend::VertexAttributeStream::POSITION,
Renderer::Backend::Format::R32G32B32_SFLOAT,
offsetof(SBaseVertex, m_Position), stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0}
}};
return g_Renderer.GetVertexInputLayout(attributes);
}
}
// static
Renderer::Backend::IVertexInputLayout* CPatchRData::GetSideVertexInputLayout()
{
const uint32_t stride = sizeof(SSideVertex);
const std::array<Renderer::Backend::SVertexAttributeFormat, 1> attributes{{
{Renderer::Backend::VertexAttributeStream::POSITION,
Renderer::Backend::Format::R32G32B32_SFLOAT,
offsetof(SSideVertex, m_Position), stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0}
}};
return g_Renderer.GetVertexInputLayout(attributes);
}
// static
Renderer::Backend::IVertexInputLayout* CPatchRData::GetWaterSurfaceVertexInputLayout(
const bool bindWaterData)
{
const uint32_t stride = sizeof(SWaterVertex);
if (bindWaterData)
{
const std::array<Renderer::Backend::SVertexAttributeFormat, 2> attributes{{
{Renderer::Backend::VertexAttributeStream::POSITION,
Renderer::Backend::Format::R32G32B32_SFLOAT,
offsetof(SWaterVertex, m_Position), stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0},
// UV1 will be used only in case of bindWaterData.
{Renderer::Backend::VertexAttributeStream::UV1,
Renderer::Backend::Format::R32G32_SFLOAT,
offsetof(SWaterVertex, m_WaterData), stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0}
}};
return g_Renderer.GetVertexInputLayout(attributes);
}
else
{
const std::array<Renderer::Backend::SVertexAttributeFormat, 1> attributes{{
{Renderer::Backend::VertexAttributeStream::POSITION,
Renderer::Backend::Format::R32G32B32_SFLOAT,
offsetof(SWaterVertex, m_Position), stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0}
}};
return g_Renderer.GetVertexInputLayout(attributes);
}
}
// static
Renderer::Backend::IVertexInputLayout* CPatchRData::GetWaterShoreVertexInputLayout()
{
const uint32_t stride = sizeof(SWaterVertex);
const std::array<Renderer::Backend::SVertexAttributeFormat, 2> attributes{ {
{Renderer::Backend::VertexAttributeStream::POSITION,
Renderer::Backend::Format::R32G32B32_SFLOAT,
offsetof(SWaterVertex, m_Position), stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0},
{Renderer::Backend::VertexAttributeStream::UV1,
Renderer::Backend::Format::R32G32_SFLOAT,
offsetof(SWaterVertex, m_WaterData), stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0}
}};
return g_Renderer.GetVertexInputLayout(attributes);
}
CPatchRData::CPatchRData(CPatch* patch, CSimulation2* simulation) :
m_Patch(patch), m_Simulation(simulation)
{
@ -716,6 +855,7 @@ using ShaderTechniqueBatches = PooledBatchMap<std::pair<CStrIntern, CShaderDefin
void CPatchRData::RenderBases(
Renderer::Backend::IDeviceCommandContext* deviceCommandContext,
Renderer::Backend::IVertexInputLayout* vertexInputLayout,
const std::vector<CPatchRData*>& patches, const CShaderDefines& context, ShadowMap* shadow)
{
PROFILE3("render terrain bases");
@ -817,23 +957,7 @@ void CPatchRData::RenderBases(
{
ENSURE(!itv->first->GetBuffer()->IsDynamic());
const uint32_t stride = sizeof(SBaseVertex);
deviceCommandContext->SetVertexAttributeFormat(
Renderer::Backend::VertexAttributeStream::POSITION,
Renderer::Backend::Format::R32G32B32_SFLOAT,
offsetof(SBaseVertex, m_Position), stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0);
deviceCommandContext->SetVertexAttributeFormat(
Renderer::Backend::VertexAttributeStream::NORMAL,
Renderer::Backend::Format::R32G32B32_SFLOAT,
offsetof(SBaseVertex, m_Normal), stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0);
deviceCommandContext->SetVertexAttributeFormat(
Renderer::Backend::VertexAttributeStream::UV0,
Renderer::Backend::Format::R32G32B32_SFLOAT,
offsetof(SBaseVertex, m_Position), stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0);
deviceCommandContext->SetVertexInputLayout(vertexInputLayout);
deviceCommandContext->SetVertexBuffer(0, itv->first->GetBuffer(), 0);
@ -891,6 +1015,7 @@ struct SBlendStackItem
void CPatchRData::RenderBlends(
Renderer::Backend::IDeviceCommandContext* deviceCommandContext,
Renderer::Backend::IVertexInputLayout* vertexInputLayout,
const std::vector<CPatchRData*>& patches, const CShaderDefines& context, ShadowMap* shadow)
{
PROFILE3("render terrain blends");
@ -1065,28 +1190,7 @@ void CPatchRData::RenderBlends(
ENSURE(!itv->first->GetBuffer()->IsDynamic());
const uint32_t stride = sizeof(SBlendVertex);
deviceCommandContext->SetVertexAttributeFormat(
Renderer::Backend::VertexAttributeStream::POSITION,
Renderer::Backend::Format::R32G32B32_SFLOAT,
offsetof(SBlendVertex, m_Position), stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0);
deviceCommandContext->SetVertexAttributeFormat(
Renderer::Backend::VertexAttributeStream::NORMAL,
Renderer::Backend::Format::R32G32B32_SFLOAT,
offsetof(SBlendVertex, m_Normal), stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0);
deviceCommandContext->SetVertexAttributeFormat(
Renderer::Backend::VertexAttributeStream::UV0,
Renderer::Backend::Format::R32G32B32_SFLOAT,
offsetof(SBlendVertex, m_Position), stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0);
deviceCommandContext->SetVertexAttributeFormat(
Renderer::Backend::VertexAttributeStream::UV1,
Renderer::Backend::Format::R32G32_SFLOAT,
offsetof(SBlendVertex, m_AlphaUVs), stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0);
deviceCommandContext->SetVertexInputLayout(vertexInputLayout);
deviceCommandContext->SetVertexBuffer(0, itv->first->GetBuffer(), 0);
}
@ -1114,7 +1218,8 @@ void CPatchRData::RenderBlends(
void CPatchRData::RenderStreams(
Renderer::Backend::IDeviceCommandContext* deviceCommandContext,
const std::vector<CPatchRData*>& patches, const bool bindPositionAsTexCoord)
Renderer::Backend::IVertexInputLayout* vertexInputLayout,
const std::vector<CPatchRData*>& patches)
{
PROFILE3("render terrain streams");
@ -1143,21 +1248,7 @@ void CPatchRData::RenderStreams(
PROFILE_END("compute batches");
const uint32_t stride = sizeof(SBaseVertex);
deviceCommandContext->SetVertexAttributeFormat(
Renderer::Backend::VertexAttributeStream::POSITION,
Renderer::Backend::Format::R32G32B32_SFLOAT,
offsetof(SBaseVertex, m_Position), stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0);
if (bindPositionAsTexCoord)
{
deviceCommandContext->SetVertexAttributeFormat(
Renderer::Backend::VertexAttributeStream::UV0,
Renderer::Backend::Format::R32G32B32_SFLOAT,
offsetof(SBaseVertex, m_Position), stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0);
}
deviceCommandContext->SetVertexInputLayout(vertexInputLayout);
// Render each batch
for (const std::pair<CVertexBuffer* const, StreamIndexBufferBatches>& streamBatch : batches)
@ -1216,6 +1307,7 @@ void CPatchRData::RenderOutline()
void CPatchRData::RenderSides(
Renderer::Backend::IDeviceCommandContext* deviceCommandContext,
Renderer::Backend::IVertexInputLayout* vertexInputLayout,
const std::vector<CPatchRData*>& patches)
{
PROFILE3("render terrain sides");
@ -1224,12 +1316,7 @@ void CPatchRData::RenderSides(
if (patches.empty())
return;
const uint32_t stride = sizeof(SSideVertex);
deviceCommandContext->SetVertexAttributeFormat(
Renderer::Backend::VertexAttributeStream::POSITION,
Renderer::Backend::Format::R32G32B32_SFLOAT,
offsetof(SSideVertex, m_Position), stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0);
deviceCommandContext->SetVertexInputLayout(vertexInputLayout);
CVertexBuffer* lastVB = nullptr;
for (CPatchRData* patch : patches)
@ -1481,7 +1568,7 @@ void CPatchRData::BuildWater()
void CPatchRData::RenderWaterSurface(
Renderer::Backend::IDeviceCommandContext* deviceCommandContext,
const bool bindWaterData)
Renderer::Backend::IVertexInputLayout* vertexInputLayout)
{
ASSERT(m_UpdateFlags == 0);
@ -1494,19 +1581,7 @@ void CPatchRData::RenderWaterSurface(
const uint32_t stride = sizeof(SWaterVertex);
const uint32_t firstVertexOffset = m_VBWater->m_Index * stride;
deviceCommandContext->SetVertexAttributeFormat(
Renderer::Backend::VertexAttributeStream::POSITION,
Renderer::Backend::Format::R32G32B32_SFLOAT,
offsetof(SWaterVertex, m_Position), stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0);
if (bindWaterData)
{
deviceCommandContext->SetVertexAttributeFormat(
Renderer::Backend::VertexAttributeStream::UV1,
Renderer::Backend::Format::R32G32_SFLOAT,
offsetof(SWaterVertex, m_WaterData), stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0);
}
deviceCommandContext->SetVertexInputLayout(vertexInputLayout);
deviceCommandContext->SetVertexBuffer(
0, m_VBWater->m_Owner->GetBuffer(), firstVertexOffset);
@ -1519,7 +1594,8 @@ void CPatchRData::RenderWaterSurface(
}
void CPatchRData::RenderWaterShore(
Renderer::Backend::IDeviceCommandContext* deviceCommandContext)
Renderer::Backend::IDeviceCommandContext* deviceCommandContext,
Renderer::Backend::IVertexInputLayout* vertexInputLayout)
{
ASSERT(m_UpdateFlags == 0);
@ -1532,16 +1608,7 @@ void CPatchRData::RenderWaterShore(
const uint32_t stride = sizeof(SWaterVertex);
const uint32_t firstVertexOffset = m_VBWaterShore->m_Index * stride;
deviceCommandContext->SetVertexAttributeFormat(
Renderer::Backend::VertexAttributeStream::POSITION,
Renderer::Backend::Format::R32G32B32_SFLOAT,
offsetof(SWaterVertex, m_Position), stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0);
deviceCommandContext->SetVertexAttributeFormat(
Renderer::Backend::VertexAttributeStream::UV1,
Renderer::Backend::Format::R32G32_SFLOAT,
offsetof(SWaterVertex, m_WaterData), stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0);
deviceCommandContext->SetVertexInputLayout(vertexInputLayout);
deviceCommandContext->SetVertexBuffer(
0, m_VBWaterShore->m_Owner->GetBuffer(), firstVertexOffset);

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2022 Wildfire Games.
/* Copyright (C) 2023 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -44,15 +44,26 @@ public:
CPatchRData(CPatch* patch, CSimulation2* simulation);
~CPatchRData();
static Renderer::Backend::IVertexInputLayout* GetBaseVertexInputLayout();
static Renderer::Backend::IVertexInputLayout* GetBlendVertexInputLayout();
static Renderer::Backend::IVertexInputLayout* GetStreamVertexInputLayout(
const bool bindPositionAsTexCoord);
static Renderer::Backend::IVertexInputLayout* GetSideVertexInputLayout();
static Renderer::Backend::IVertexInputLayout* GetWaterSurfaceVertexInputLayout(
const bool bindWaterData);
static Renderer::Backend::IVertexInputLayout* GetWaterShoreVertexInputLayout();
void Update(CSimulation2* simulation);
void RenderOutline();
void RenderPriorities(CTextRenderer& textRenderer);
void RenderWaterSurface(
Renderer::Backend::IDeviceCommandContext* deviceCommandContext,
const bool bindWaterData);
Renderer::Backend::IVertexInputLayout* vertexInputLayout);
void RenderWaterShore(
Renderer::Backend::IDeviceCommandContext* deviceCommandContext);
Renderer::Backend::IDeviceCommandContext* deviceCommandContext,
Renderer::Backend::IVertexInputLayout* vertexInputLayout);
CPatch* GetPatch() { return m_Patch; }
@ -60,15 +71,19 @@ public:
static void RenderBases(
Renderer::Backend::IDeviceCommandContext* deviceCommandContext,
Renderer::Backend::IVertexInputLayout* vertexInputLayout,
const std::vector<CPatchRData*>& patches, const CShaderDefines& context, ShadowMap* shadow);
static void RenderBlends(
Renderer::Backend::IDeviceCommandContext* deviceCommandContext,
Renderer::Backend::IVertexInputLayout* vertexInputLayout,
const std::vector<CPatchRData*>& patches, const CShaderDefines& context, ShadowMap* shadow);
static void RenderStreams(
Renderer::Backend::IDeviceCommandContext* deviceCommandContext,
const std::vector<CPatchRData*>& patches, const bool bindPositionAsTexCoord);
Renderer::Backend::IVertexInputLayout* vertexInputLayout,
const std::vector<CPatchRData*>& patches);
static void RenderSides(
Renderer::Backend::IDeviceCommandContext* deviceCommandContext,
Renderer::Backend::IVertexInputLayout* vertexInputLayout,
const std::vector<CPatchRData*>& patches);
static void PrepareShader(ShadowMap* shadow);

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2022 Wildfire Games.
/* Copyright (C) 2023 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -87,6 +87,16 @@ void CPostprocManager::Initialize()
if (m_IsInitialized)
return;
const std::array<Renderer::Backend::SVertexAttributeFormat, 2> attributes{{
{Renderer::Backend::VertexAttributeStream::POSITION,
Renderer::Backend::Format::R32G32_SFLOAT, 0, sizeof(float) * 2,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0},
{Renderer::Backend::VertexAttributeStream::UV0,
Renderer::Backend::Format::R32G32_SFLOAT, 0, sizeof(float) * 2,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 1},
}};
m_VertexInputLayout = g_Renderer.GetVertexInputLayout(attributes);
const uint32_t maxSamples = g_VideoMode.GetBackendDevice()->GetCapabilities().maxSampleCount;
const uint32_t possibleSampleCounts[] = {2, 4, 8, 16};
std::copy_if(
@ -259,14 +269,7 @@ void CPostprocManager::ApplyBlurDownscale2x(
1.0f, 1.0f
};
deviceCommandContext->SetVertexAttributeFormat(
Renderer::Backend::VertexAttributeStream::POSITION,
Renderer::Backend::Format::R32G32_SFLOAT, 0, sizeof(float) * 2,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0);
deviceCommandContext->SetVertexAttributeFormat(
Renderer::Backend::VertexAttributeStream::UV0,
Renderer::Backend::Format::R32G32_SFLOAT, 0, sizeof(float) * 2,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 1);
deviceCommandContext->SetVertexInputLayout(m_VertexInputLayout);
deviceCommandContext->SetVertexBufferData(
0, quadVerts, std::size(quadVerts) * sizeof(quadVerts[0]));
@ -329,14 +332,7 @@ void CPostprocManager::ApplyBlurGauss(
1.0f, 1.0f
};
deviceCommandContext->SetVertexAttributeFormat(
Renderer::Backend::VertexAttributeStream::POSITION,
Renderer::Backend::Format::R32G32_SFLOAT, 0, sizeof(float) * 2,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0);
deviceCommandContext->SetVertexAttributeFormat(
Renderer::Backend::VertexAttributeStream::UV0,
Renderer::Backend::Format::R32G32_SFLOAT, 0, sizeof(float) * 2,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 1);
deviceCommandContext->SetVertexInputLayout(m_VertexInputLayout);
deviceCommandContext->SetVertexBufferData(
0, quadVerts, std::size(quadVerts) * sizeof(quadVerts[0]));
@ -368,14 +364,7 @@ void CPostprocManager::ApplyBlurGauss(
deviceCommandContext->SetUniform(
shader->GetBindingSlot(str_texSize), inWidth, inHeight);
deviceCommandContext->SetVertexAttributeFormat(
Renderer::Backend::VertexAttributeStream::POSITION,
Renderer::Backend::Format::R32G32_SFLOAT, 0, sizeof(float) * 2,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0);
deviceCommandContext->SetVertexAttributeFormat(
Renderer::Backend::VertexAttributeStream::UV0,
Renderer::Backend::Format::R32G32_SFLOAT, 0, sizeof(float) * 2,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 1);
deviceCommandContext->SetVertexInputLayout(m_VertexInputLayout);
deviceCommandContext->SetVertexBufferData(
0, quadVerts, std::size(quadVerts) * sizeof(quadVerts[0]));
@ -498,14 +487,7 @@ void CPostprocManager::ApplyEffect(
1.0f, 1.0f
};
deviceCommandContext->SetVertexAttributeFormat(
Renderer::Backend::VertexAttributeStream::POSITION,
Renderer::Backend::Format::R32G32_SFLOAT, 0, sizeof(float) * 2,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0);
deviceCommandContext->SetVertexAttributeFormat(
Renderer::Backend::VertexAttributeStream::UV0,
Renderer::Backend::Format::R32G32_SFLOAT, 0, sizeof(float) * 2,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 1);
deviceCommandContext->SetVertexInputLayout(m_VertexInputLayout);
deviceCommandContext->SetVertexBufferData(
0, quadVerts, std::size(quadVerts) * sizeof(quadVerts[0]));

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2022 Wildfire Games.
/* Copyright (C) 2023 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -22,6 +22,7 @@
#include "ps/CStr.h"
#include "renderer/backend/IFramebuffer.h"
#include "renderer/backend/IDeviceCommandContext.h"
#include "renderer/backend/IShaderProgram.h"
#include "renderer/backend/ITexture.h"
#include <array>
@ -118,6 +119,8 @@ private:
// Indicates which of the ping-pong buffers is used for reading and which for drawing.
bool m_WhichBuffer;
Renderer::Backend::IVertexInputLayout* m_VertexInputLayout = nullptr;
// The name and shader technique we are using. "default" name means no technique is used
// (i.e. while we do allocate the buffers, no effects are rendered).
CStrW m_PostProcEffect;

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2022 Wildfire Games.
/* Copyright (C) 2023 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -27,6 +27,7 @@
#include "graphics/TerrainTextureManager.h"
#include "i18n/L10n.h"
#include "lib/allocators/shared_ptr.h"
#include "lib/hash.h"
#include "lib/tex/tex.h"
#include "gui/GUIManager.h"
#include "ps/CConsole.h"
@ -271,6 +272,15 @@ public:
CFontManager fontManager;
struct VertexAttributesHash
{
size_t operator()(const std::vector<Renderer::Backend::SVertexAttributeFormat>& attributes) const;
};
std::unordered_map<
std::vector<Renderer::Backend::SVertexAttributeFormat>,
std::unique_ptr<Renderer::Backend::IVertexInputLayout>, VertexAttributesHash> vertexInputLayouts;
Internals() :
IsOpen(false), ShadersDirty(true), profileTable(g_Renderer.m_Stats),
deviceCommandContext(g_VideoMode.GetBackendDevice()->CreateCommandContext()),
@ -279,6 +289,23 @@ public:
}
};
size_t CRenderer::Internals::VertexAttributesHash::operator()(
const std::vector<Renderer::Backend::SVertexAttributeFormat>& attributes) const
{
size_t seed = 0;
hash_combine(seed, attributes.size());
for (const Renderer::Backend::SVertexAttributeFormat& attribute : attributes)
{
hash_combine(seed, attribute.stream);
hash_combine(seed, attribute.format);
hash_combine(seed, attribute.offset);
hash_combine(seed, attribute.stride);
hash_combine(seed, attribute.rate);
hash_combine(seed, attribute.bindingSlot);
}
return seed;
}
CRenderer::CRenderer()
{
TIMER(L"InitRenderer");
@ -336,6 +363,8 @@ bool CRenderer::Open(int width, int height)
// Validate the currently selected render path
SetRenderPath(g_RenderingOptions.GetRenderPath());
m->debugRenderer.Initialize();
if (m->postprocManager.IsEnabled())
m->postprocManager.Initialize();
@ -853,3 +882,13 @@ Renderer::Backend::IDeviceCommandContext* CRenderer::GetDeviceCommandContext()
{
return m->deviceCommandContext.get();
}
Renderer::Backend::IVertexInputLayout* CRenderer::GetVertexInputLayout(
const PS::span<const Renderer::Backend::SVertexAttributeFormat> attributes)
{
const auto [it, inserted] = m->vertexInputLayouts.emplace(
std::vector<Renderer::Backend::SVertexAttributeFormat>{attributes.begin(), attributes.end()}, nullptr);
if (inserted)
it->second = g_VideoMode.GetBackendDevice()->CreateVertexInputLayout(attributes);
return it->second.get();
}

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2022 Wildfire Games.
/* Copyright (C) 2023 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -21,8 +21,10 @@
#include "graphics/Camera.h"
#include "graphics/ShaderDefines.h"
#include "graphics/ShaderProgramPtr.h"
#include "ps/containers/Span.h"
#include "ps/Singleton.h"
#include "renderer/backend/IDeviceCommandContext.h"
#include "renderer/backend/IShaderProgram.h"
#include "renderer/RenderingOptions.h"
#include "renderer/Scene.h"
@ -132,6 +134,16 @@ public:
Renderer::Backend::IDeviceCommandContext* GetDeviceCommandContext();
/**
* Returns a cached vertex input layout. The renderer owns the layout to be
* able to share it between different clients. As backend should have
* as few different layouts as possible.
* The function isn't cheap so it should be called as rarely as possible.
* TODO: we need to make VertexArray less error prone by passing layout.
*/
Renderer::Backend::IVertexInputLayout* GetVertexInputLayout(
const PS::span<const Renderer::Backend::SVertexAttributeFormat> attributes);
protected:
friend class CPatchRData;
friend class CDecalRData;

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2022 Wildfire Games.
/* Copyright (C) 2023 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -268,6 +268,8 @@ void CSceneRenderer::Initialize()
{
// Let component renderers perform one-time initialization after graphics capabilities and
// the shader path have been determined.
m->waterManager.Initialize();
m->terrainRenderer.Initialize();
m->overlayRenderer.Initialize();
}

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2022 Wildfire Games.
/* Copyright (C) 2023 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -478,6 +478,13 @@ void SilhouetteRenderer::RenderDebugOverlays(
pipelineStateDesc.rasterizationState.polygonMode = Renderer::Backend::PolygonMode::LINE;
pipelineStateDesc.rasterizationState.cullMode = Renderer::Backend::CullMode::NONE;
});
const std::array<Renderer::Backend::SVertexAttributeFormat, 1> attributes{{
{Renderer::Backend::VertexAttributeStream::POSITION,
Renderer::Backend::Format::R32G32_SFLOAT, 0, sizeof(float) * 2,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0}
}};
m_VertexInputLayout = g_Renderer.GetVertexInputLayout(attributes);
}
deviceCommandContext->BeginPass();
@ -503,10 +510,7 @@ void SilhouetteRenderer::RenderDebugOverlays(
r.x0, r.y1,
};
deviceCommandContext->SetVertexAttributeFormat(
Renderer::Backend::VertexAttributeStream::POSITION,
Renderer::Backend::Format::R32G32_SFLOAT, 0, sizeof(float) * 2,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0);
deviceCommandContext->SetVertexInputLayout(m_VertexInputLayout);
deviceCommandContext->SetVertexBufferData(
0, vertices, std::size(vertices) * sizeof(vertices[0]));

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2022 Wildfire Games.
/* Copyright (C) 2023 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -22,6 +22,7 @@
#include "graphics/ShaderTechniquePtr.h"
#include "maths/BoundingBoxAligned.h"
#include "renderer/backend/IDeviceCommandContext.h"
#include "renderer/backend/IShaderProgram.h"
class CCamera;
class CModel;
@ -78,6 +79,7 @@ private:
std::vector<SOverlaySphere> m_DebugSpheres;
CShaderTechniquePtr m_ShaderTech;
Renderer::Backend::IVertexInputLayout* m_VertexInputLayout = nullptr;
};
#endif // INCLUDED_SILHOUETTERENDERER

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2022 Wildfire Games.
/* Copyright (C) 2023 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -249,14 +249,7 @@ void SkyManager::RenderSky(
const uint32_t stride = m_VertexArray.GetStride();
const uint32_t firstVertexOffset = m_VertexArray.GetOffset() * stride;
deviceCommandContext->SetVertexAttributeFormat(
Renderer::Backend::VertexAttributeStream::POSITION, m_AttributePosition.format,
m_AttributePosition.offset, stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0);
deviceCommandContext->SetVertexAttributeFormat(
Renderer::Backend::VertexAttributeStream::UV0, m_AttributeUV.format,
m_AttributeUV.offset, stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0);
deviceCommandContext->SetVertexInputLayout(m_VertexInputLayout);
deviceCommandContext->SetVertexBuffer(
0, m_VertexArray.GetBuffer(), firstVertexOffset);
@ -343,4 +336,15 @@ void SkyManager::CreateSkyCube()
m_VertexArray.Upload();
m_VertexArray.FreeBackingStore();
const uint32_t stride = m_VertexArray.GetStride();
const std::array<Renderer::Backend::SVertexAttributeFormat, 2> attributes{{
{Renderer::Backend::VertexAttributeStream::POSITION,
m_AttributePosition.format, m_AttributePosition.offset, stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0},
{Renderer::Backend::VertexAttributeStream::UV0,
m_AttributeUV.format, m_AttributeUV.offset, stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0}
}};
m_VertexInputLayout = g_Renderer.GetVertexInputLayout(attributes);
}

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2022 Wildfire Games.
/* Copyright (C) 2023 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -24,6 +24,7 @@
#include "graphics/Texture.h"
#include "renderer/backend/IDeviceCommandContext.h"
#include "renderer/backend/IShaderProgram.h"
#include "renderer/backend/ITexture.h"
#include "renderer/VertexArray.h"
@ -107,6 +108,8 @@ private:
VertexArray m_VertexArray;
VertexArray::Attribute m_AttributePosition;
VertexArray::Attribute m_AttributeUV;
Renderer::Backend::IVertexInputLayout* m_VertexInputLayout = nullptr;
};

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2022 Wildfire Games.
/* Copyright (C) 2023 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -148,6 +148,14 @@ TerrainOverlay::TerrainOverlay(
m_OverlayTechOutline = CreateOverlayOutlineShaderTechnique(false);
m_OverlayTechOutlineHidden = CreateOverlayOutlineShaderTechnique(true);
const std::array<Renderer::Backend::SVertexAttributeFormat, 1> attributes{{
{Renderer::Backend::VertexAttributeStream::POSITION,
Renderer::Backend::Format::R32G32B32_SFLOAT, 0, sizeof(float) * 3,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0}
}};
m_VertexInputLayout = g_Renderer.GetVertexInputLayout(attributes);
}
void TerrainOverlay::StartRender()
@ -254,10 +262,7 @@ void TerrainOverlay::RenderTile(
deviceCommandContext->SetUniform(
overlayShader->GetBindingSlot(str_color), color.AsFloatArray());
deviceCommandContext->SetVertexAttributeFormat(
Renderer::Backend::VertexAttributeStream::POSITION,
Renderer::Backend::Format::R32G32B32_SFLOAT, 0, 0,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0);
deviceCommandContext->SetVertexInputLayout(m_VertexInputLayout);
deviceCommandContext->SetVertexBufferData(
0, vertices.data(), vertices.size() * sizeof(vertices[0]));
@ -308,10 +313,7 @@ void TerrainOverlay::RenderTileOutline(
deviceCommandContext->SetUniform(
overlayShader->GetBindingSlot(str_color), color.AsFloatArray());
deviceCommandContext->SetVertexAttributeFormat(
Renderer::Backend::VertexAttributeStream::POSITION,
Renderer::Backend::Format::R32G32B32_SFLOAT, 0, 0,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0);
deviceCommandContext->SetVertexInputLayout(m_VertexInputLayout);
deviceCommandContext->SetVertexBufferData(
0, vertices.data(), vertices.size() * sizeof(vertices[0]));

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2022 Wildfire Games.
/* Copyright (C) 2023 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -26,6 +26,7 @@
#include "graphics/ShaderTechniquePtr.h"
#include "renderer/backend/ITexture.h"
#include "renderer/backend/IDeviceCommandContext.h"
#include "renderer/backend/IShaderProgram.h"
#include "renderer/backend/PipelineState.h"
struct CColor;
@ -184,6 +185,8 @@ private:
CShaderTechniquePtr m_OverlayTechTile, m_OverlayTechTileHidden;
CShaderTechniquePtr m_OverlayTechOutline, m_OverlayTechOutlineHidden;
Renderer::Backend::IVertexInputLayout* m_VertexInputLayout = nullptr;
};
/**

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2022 Wildfire Games.
/* Copyright (C) 2023 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -83,6 +83,19 @@ struct TerrainRendererInternals
CShaderTechniquePtr shaderTechniqueSolid, shaderTechniqueSolidDepthTest;
Renderer::Backend::IVertexInputLayout* overlayVertexInputLayout = nullptr;
Renderer::Backend::IVertexInputLayout* decalsVertexInputLayout = nullptr;
Renderer::Backend::IVertexInputLayout* baseVertexInputLayout = nullptr;
Renderer::Backend::IVertexInputLayout* blendVertexInputLayout = nullptr;
Renderer::Backend::IVertexInputLayout* streamVertexInputLayout = nullptr;
Renderer::Backend::IVertexInputLayout* streamWithPositionAsTexCoordVertexInputLayout = nullptr;
Renderer::Backend::IVertexInputLayout* sideVertexInputLayout = nullptr;
Renderer::Backend::IVertexInputLayout* waterSurfaceVertexInputLayout = nullptr;
Renderer::Backend::IVertexInputLayout* waterSurfaceWithDataVertexInputLayout = nullptr;
Renderer::Backend::IVertexInputLayout* waterShoreVertexInputLayout = nullptr;
CSimulation2* simulation;
};
@ -101,6 +114,32 @@ TerrainRenderer::~TerrainRenderer()
delete m;
}
void TerrainRenderer::Initialize()
{
const std::array<Renderer::Backend::SVertexAttributeFormat, 2> overlayAttributes{{
{Renderer::Backend::VertexAttributeStream::POSITION,
Renderer::Backend::Format::R32G32B32_SFLOAT, 0, sizeof(float) * 3,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0},
{Renderer::Backend::VertexAttributeStream::UV0,
Renderer::Backend::Format::R32G32B32_SFLOAT, 0, sizeof(float) * 3,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0}
}};
m->overlayVertexInputLayout = g_Renderer.GetVertexInputLayout(overlayAttributes);
m->decalsVertexInputLayout = CDecalRData::GetVertexInputLayout();
m->baseVertexInputLayout = CPatchRData::GetBaseVertexInputLayout();
m->blendVertexInputLayout = CPatchRData::GetBlendVertexInputLayout();
m->streamVertexInputLayout = CPatchRData::GetStreamVertexInputLayout(false);
m->streamWithPositionAsTexCoordVertexInputLayout =
CPatchRData::GetStreamVertexInputLayout(true);
m->sideVertexInputLayout = CPatchRData::GetSideVertexInputLayout();
m->waterSurfaceVertexInputLayout = CPatchRData::GetWaterSurfaceVertexInputLayout(false);
m->waterSurfaceWithDataVertexInputLayout = CPatchRData::GetWaterSurfaceVertexInputLayout(true);
m->waterShoreVertexInputLayout = CPatchRData::GetWaterShoreVertexInputLayout();
}
void TerrainRenderer::SetSimulation(CSimulation2* simulation)
{
m->simulation = simulation;
@ -190,7 +229,8 @@ void TerrainRenderer::RenderTerrainOverlayTexture(
debugOverlayShader->GetBindingSlot(str_transform), transform.AsFloatArray());
deviceCommandContext->SetUniform(
debugOverlayShader->GetBindingSlot(str_textureTransform), textureTransform.AsFloatArray());
CPatchRData::RenderStreams(deviceCommandContext, visiblePatches, true);
CPatchRData::RenderStreams(
deviceCommandContext, m->streamWithPositionAsTexCoordVertexInputLayout, visiblePatches);
// To make the overlay visible over water, render an additional map-sized
// water-height patch.
@ -211,14 +251,7 @@ void TerrainRenderer::RenderTerrainOverlayTexture(
waterBounds[0].X, height, waterBounds[1].Z
};
deviceCommandContext->SetVertexAttributeFormat(
Renderer::Backend::VertexAttributeStream::POSITION,
Renderer::Backend::Format::R32G32B32_SFLOAT, 0, 0,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0);
deviceCommandContext->SetVertexAttributeFormat(
Renderer::Backend::VertexAttributeStream::UV0,
Renderer::Backend::Format::R32G32B32_SFLOAT, 0, 0,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0);
deviceCommandContext->SetVertexInputLayout(m->overlayVertexInputLayout);
deviceCommandContext->SetVertexBufferData(
0, waterPos, std::size(waterPos) * sizeof(waterPos[0]));
@ -312,16 +345,20 @@ void TerrainRenderer::RenderTerrainShader(
deviceCommandContext->SetUniform(
shaderSolid->GetBindingSlot(str_color), 0.0f, 0.0f, 0.0f, 1.0f);
CPatchRData::RenderSides(deviceCommandContext, visiblePatches);
CPatchRData::RenderSides(
deviceCommandContext, m->sideVertexInputLayout, visiblePatches);
deviceCommandContext->EndPass();
CPatchRData::RenderBases(deviceCommandContext, visiblePatches, context, shadow);
CPatchRData::RenderBases(
deviceCommandContext, m->baseVertexInputLayout, visiblePatches, context, shadow);
// render blend passes for each patch
CPatchRData::RenderBlends(deviceCommandContext, visiblePatches, context, shadow);
CPatchRData::RenderBlends(
deviceCommandContext, m->blendVertexInputLayout, visiblePatches, context, shadow);
CDecalRData::RenderDecals(deviceCommandContext, visibleDecals, context, shadow);
CDecalRData::RenderDecals(
deviceCommandContext, m->decalsVertexInputLayout, visibleDecals, context, shadow);
}
///////////////////////////////////////////////////////////////////
@ -352,7 +389,8 @@ void TerrainRenderer::RenderPatches(
deviceCommandContext->SetUniform(
solidShader->GetBindingSlot(str_color), color.AsFloatArray());
CPatchRData::RenderStreams(deviceCommandContext, visiblePatches, false);
CPatchRData::RenderStreams(
deviceCommandContext, m->streamVertexInputLayout, visiblePatches);
deviceCommandContext->EndPass();
}
@ -606,9 +644,10 @@ bool TerrainRenderer::RenderFancyWater(
for (CPatchRData* data : m->visiblePatches[cullGroup])
{
data->RenderWaterSurface(deviceCommandContext, true);
data->RenderWaterSurface(
deviceCommandContext, m->waterSurfaceWithDataVertexInputLayout);
if (waterManager.m_WaterFancyEffects)
data->RenderWaterShore(deviceCommandContext);
data->RenderWaterShore(deviceCommandContext, m->waterShoreVertexInputLayout);
}
deviceCommandContext->EndPass();
@ -659,11 +698,10 @@ void TerrainRenderer::RenderSimpleWater(
deviceCommandContext->SetUniform(
waterSimpleShader->GetBindingSlot(str_color), waterManager.m_WaterColor.AsFloatArray());
std::vector<CPatchRData*>& visiblePatches = m->visiblePatches[cullGroup];
for (size_t i = 0; i < visiblePatches.size(); ++i)
for (CPatchRData* data : m->visiblePatches[cullGroup])
{
CPatchRData* data = visiblePatches[i];
data->RenderWaterSurface(deviceCommandContext, false);
data->RenderWaterSurface(
deviceCommandContext, m->waterSurfaceVertexInputLayout);
}
deviceCommandContext->EndPass();
@ -722,7 +760,7 @@ void TerrainRenderer::RenderWaterFoamOccluders(
dummyShader->GetBindingSlot(str_color), 0.0f, 0.0f, 0.0f, 0.0f);
for (CPatchRData* data : m->visiblePatches[cullGroup])
data->RenderWaterShore(deviceCommandContext);
data->RenderWaterShore(deviceCommandContext, m->waterShoreVertexInputLayout);
deviceCommandContext->EndPass();

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2022 Wildfire Games.
/* Copyright (C) 2023 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -54,6 +54,8 @@ public:
TerrainRenderer();
~TerrainRenderer();
void Initialize();
/**
* Set the simulation context for this frame.
* Call at start of frame, before any other Submits.

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2022 Wildfire Games.
/* Copyright (C) 2023 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -35,8 +35,30 @@
* because it allows you to work with variable amounts of vertices and indices more easily. New code should prefer
* to use VertexArray where possible, though. */
// static
Renderer::Backend::IVertexInputLayout* CTexturedLineRData::GetVertexInputLayout()
{
const uint32_t stride = sizeof(CTexturedLineRData::SVertex);
const std::array<Renderer::Backend::SVertexAttributeFormat, 3> attributes{{
{Renderer::Backend::VertexAttributeStream::POSITION,
Renderer::Backend::Format::R32G32B32_SFLOAT,
offsetof(CTexturedLineRData::SVertex, m_Position), stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0},
{Renderer::Backend::VertexAttributeStream::UV0,
Renderer::Backend::Format::R32G32_SFLOAT,
offsetof(CTexturedLineRData::SVertex, m_UV), stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0},
{Renderer::Backend::VertexAttributeStream::UV1,
Renderer::Backend::Format::R32G32_SFLOAT,
offsetof(CTexturedLineRData::SVertex, m_UV), stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0}
}};
return g_Renderer.GetVertexInputLayout(attributes);
}
void CTexturedLineRData::Render(
Renderer::Backend::IDeviceCommandContext* deviceCommandContext,
Renderer::Backend::IVertexInputLayout* vertexInputLayout,
const SOverlayTexturedLine& line, Renderer::Backend::IShaderProgram* shader)
{
if (!m_VB || !m_VBIndices)
@ -57,23 +79,7 @@ void CTexturedLineRData::Render(
deviceCommandContext->SetUniform(
shader->GetBindingSlot(str_objectColor), line.m_Color.AsFloatArray());
const uint32_t stride = sizeof(CTexturedLineRData::SVertex);
deviceCommandContext->SetVertexAttributeFormat(
Renderer::Backend::VertexAttributeStream::POSITION,
Renderer::Backend::Format::R32G32B32_SFLOAT,
offsetof(CTexturedLineRData::SVertex, m_Position), stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0);
deviceCommandContext->SetVertexAttributeFormat(
Renderer::Backend::VertexAttributeStream::UV0,
Renderer::Backend::Format::R32G32_SFLOAT,
offsetof(CTexturedLineRData::SVertex, m_UV), stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0);
deviceCommandContext->SetVertexAttributeFormat(
Renderer::Backend::VertexAttributeStream::UV1,
Renderer::Backend::Format::R32G32_SFLOAT,
offsetof(CTexturedLineRData::SVertex, m_UV), stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0);
deviceCommandContext->SetVertexInputLayout(vertexInputLayout);
deviceCommandContext->SetVertexBuffer(0, m_VB->m_Owner->GetBuffer(), 0);

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2022 Wildfire Games.
/* Copyright (C) 2023 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -24,6 +24,7 @@
#include "graphics/TextureManager.h"
#include "maths/BoundingBoxAligned.h"
#include "renderer/backend/IDeviceCommandContext.h"
#include "renderer/backend/IShaderProgram.h"
#include "renderer/VertexBufferManager.h"
class CFrustum;
@ -47,12 +48,14 @@ class CTexturedLineRData : public CRenderData
NONCOPYABLE(CTexturedLineRData);
public:
CTexturedLineRData() = default;
~CTexturedLineRData() = default;
static Renderer::Backend::IVertexInputLayout* GetVertexInputLayout();
void Update(const SOverlayTexturedLine& line);
void Render(Renderer::Backend::IDeviceCommandContext* deviceCommandContext,
Renderer::Backend::IVertexInputLayout* vertexInputLayout,
const SOverlayTexturedLine& line, Renderer::Backend::IShaderProgram* shader);
bool IsVisibleInFrustum(const CFrustum& frustum) const;

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2022 Wildfire Games.
/* Copyright (C) 2023 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -31,7 +31,7 @@
namespace
{
size_t GetAttributeSize(const Renderer::Backend::Format format)
uint32_t GetAttributeSize(const Renderer::Backend::Format format)
{
switch (format)
{
@ -209,7 +209,7 @@ VertexArrayIterator<short[2]> VertexArray::Attribute::GetIterator<short[2]>() co
return vertexArray->MakeIterator<short[2]>(this);
}
static size_t RoundStride(size_t stride)
static uint32_t RoundStride(uint32_t stride)
{
if (stride <= 0)
return 0;
@ -238,7 +238,7 @@ void VertexArray::Layout()
if (attr->format == Renderer::Backend::Format::UNDEFINED)
continue;
const size_t attrSize = GetAttributeSize(attr->format);
const uint32_t attrSize = GetAttributeSize(attr->format);
ENSURE(attrSize > 0);
attr->offset = m_Stride;

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2022 Wildfire Games.
/* Copyright (C) 2023 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -142,7 +142,7 @@ public:
Renderer::Backend::Format format = Renderer::Backend::Format::UNDEFINED;
// Offset (in bytes) into a vertex structure (filled in by Layout())
size_t offset = 0;
uint32_t offset = 0;
VertexArray* vertexArray = nullptr;
@ -169,7 +169,7 @@ public:
void AddAttribute(Attribute* attr);
size_t GetNumberOfVertices() const { return m_NumberOfVertices; }
size_t GetStride() const { return m_Stride; }
uint32_t GetStride() const { return m_Stride; }
// Layout the vertex array format and create backing buffer in RAM.
// You must call Layout() after changing the number of vertices or
@ -208,7 +208,7 @@ private:
std::vector<Attribute*> m_Attributes;
CVertexBufferManager::Handle m_VB;
size_t m_Stride;
uint32_t m_Stride;
char* m_BackingStore; // 16-byte aligned, to allow fast SSE access
};

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2022 Wildfire Games.
/* Copyright (C) 2023 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -128,6 +128,39 @@ WaterManager::~WaterManager()
m_RefrFboDepthTexture.reset();
}
void WaterManager::Initialize()
{
const uint32_t stride = sizeof(SWavesVertex);
const std::array<Renderer::Backend::SVertexAttributeFormat, 6> attributes{{
{Renderer::Backend::VertexAttributeStream::POSITION,
Renderer::Backend::Format::R32G32B32_SFLOAT,
offsetof(SWavesVertex, m_BasePosition), stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0},
{Renderer::Backend::VertexAttributeStream::NORMAL,
Renderer::Backend::Format::R32G32_SFLOAT,
offsetof(SWavesVertex, m_PerpVect), stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0},
{Renderer::Backend::VertexAttributeStream::UV0,
Renderer::Backend::Format::R8G8_UINT,
offsetof(SWavesVertex, m_UV), stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0},
{Renderer::Backend::VertexAttributeStream::UV1,
Renderer::Backend::Format::R32G32B32_SFLOAT,
offsetof(SWavesVertex, m_ApexPosition), stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0},
{Renderer::Backend::VertexAttributeStream::UV2,
Renderer::Backend::Format::R32G32B32_SFLOAT,
offsetof(SWavesVertex, m_SplashPosition), stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0},
{Renderer::Backend::VertexAttributeStream::UV3,
Renderer::Backend::Format::R32G32B32_SFLOAT,
offsetof(SWavesVertex, m_RetreatPosition), stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0}
}};
m_ShoreVertexInputLayout = g_Renderer.GetVertexInputLayout(attributes);
}
///////////////////////////////////////////////////////////////////
// Progressive load of water textures
@ -872,37 +905,7 @@ void WaterManager::RenderWaves(
const uint32_t stride = sizeof(SWavesVertex);
const uint32_t firstVertexOffset = VBchunk->m_Index * stride;
deviceCommandContext->SetVertexAttributeFormat(
Renderer::Backend::VertexAttributeStream::POSITION,
Renderer::Backend::Format::R32G32B32_SFLOAT,
offsetof(SWavesVertex, m_BasePosition), stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0);
deviceCommandContext->SetVertexAttributeFormat(
Renderer::Backend::VertexAttributeStream::NORMAL,
Renderer::Backend::Format::R32G32_SFLOAT,
offsetof(SWavesVertex, m_PerpVect), stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0);
deviceCommandContext->SetVertexAttributeFormat(
Renderer::Backend::VertexAttributeStream::UV0,
Renderer::Backend::Format::R8G8_UINT,
offsetof(SWavesVertex, m_UV), stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0);
deviceCommandContext->SetVertexAttributeFormat(
Renderer::Backend::VertexAttributeStream::UV1,
Renderer::Backend::Format::R32G32B32_SFLOAT,
offsetof(SWavesVertex, m_ApexPosition), stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0);
deviceCommandContext->SetVertexAttributeFormat(
Renderer::Backend::VertexAttributeStream::UV2,
Renderer::Backend::Format::R32G32B32_SFLOAT,
offsetof(SWavesVertex, m_SplashPosition), stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0);
deviceCommandContext->SetVertexAttributeFormat(
Renderer::Backend::VertexAttributeStream::UV3,
Renderer::Backend::Format::R32G32B32_SFLOAT,
offsetof(SWavesVertex, m_RetreatPosition), stride,
Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0);
deviceCommandContext->SetVertexInputLayout(m_ShoreVertexInputLayout);
deviceCommandContext->SetUniform(
shader->GetBindingSlot(str_translation), m_ShoreWaves[a]->m_TimeDiff);

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2022 Wildfire Games.
/* Copyright (C) 2023 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -28,6 +28,7 @@
#include "maths/Vector2D.h"
#include "renderer/backend/IDeviceCommandContext.h"
#include "renderer/backend/IFramebuffer.h"
#include "renderer/backend/IShaderProgram.h"
#include "renderer/backend/ITexture.h"
#include "renderer/VertexBufferManager.h"
@ -60,6 +61,8 @@ public:
// Waves indices buffer. Only one since All Wave Objects have the same.
CVertexBufferManager::Handle m_ShoreWavesVBIndices;
Renderer::Backend::IVertexInputLayout* m_ShoreVertexInputLayout = nullptr;
size_t m_MapSize;
ssize_t m_TexSize;
@ -129,6 +132,8 @@ public:
WaterManager();
~WaterManager();
void Initialize();
/**
* LoadWaterTextures: Load water textures from within the
* progressive load framework.

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2022 Wildfire Games.
/* Copyright (C) 2023 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -19,6 +19,7 @@
#define INCLUDED_RENDERER_BACKEND_IDEVICE
#include "graphics/Color.h"
#include "ps/containers/Span.h"
#include "renderer/backend/Backend.h"
#include "renderer/backend/Format.h"
#include "renderer/backend/IBuffer.h"
@ -82,6 +83,13 @@ public:
virtual std::unique_ptr<IGraphicsPipelineState> CreateGraphicsPipelineState(
const SGraphicsPipelineStateDesc& pipelineStateDesc) = 0;
/**
* Creates a vertex input layout. It's recommended to use as few different
* layouts as posible.
*/
virtual std::unique_ptr<IVertexInputLayout> CreateVertexInputLayout(
const PS::span<const SVertexAttributeFormat> attributes) = 0;
virtual std::unique_ptr<ITexture> CreateTexture(
const char* name, const ITexture::Type type, const uint32_t usage,
const Format format, const uint32_t width, const uint32_t height,

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2022 Wildfire Games.
/* Copyright (C) 2023 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -40,6 +40,10 @@ class ITexture;
class IDeviceCommandContext : public IDeviceObject<IDeviceCommandContext>
{
public:
/**
* Binds the graphics pipeline state. It should be called only inside a
* framebuffer pass and as rarely as possible.
*/
virtual void SetGraphicsPipelineState(IGraphicsPipelineState* pipelineState) = 0;
virtual void BlitFramebuffer(
@ -95,13 +99,14 @@ public:
virtual void SetScissors(const uint32_t scissorCount, const Rect* scissors) = 0;
virtual void SetViewports(const uint32_t viewportCount, const Rect* viewports) = 0;
virtual void SetVertexAttributeFormat(
const VertexAttributeStream stream,
const Format format,
const uint32_t offset,
const uint32_t stride,
const VertexAttributeRate rate,
const uint32_t bindingSlot) = 0;
/**
* Binds the vertex input layout. It should be compatible with the shader
* program's one. It should be called only inside a framebuffer pass and as
* rarely as possible.
*/
virtual void SetVertexInputLayout(
IVertexInputLayout* vertexInputLayout) = 0;
virtual void SetVertexBuffer(
const uint32_t bindingSlot, IBuffer* buffer, const uint32_t offset) = 0;
virtual void SetVertexBufferData(

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2022 Wildfire Games.
/* Copyright (C) 2023 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -20,6 +20,7 @@
#include "lib/file/vfs/vfs_path.h"
#include "ps/CStrIntern.h"
#include "renderer/backend/Format.h"
#include "renderer/backend/IDeviceObject.h"
namespace Renderer
@ -49,6 +50,30 @@ enum class VertexAttributeRate : uint32_t
PER_INSTANCE
};
struct SVertexAttributeFormat
{
VertexAttributeStream stream;
Format format;
uint32_t offset;
uint32_t stride;
VertexAttributeRate rate;
uint32_t bindingSlot;
constexpr bool operator==(const SVertexAttributeFormat& other) const noexcept
{
return stream == other.stream && format == other.format &&
offset == other.offset && stride == other.stride &&
rate == other.rate && bindingSlot == other.bindingSlot;
}
};
/**
* IVertexInputLayout stores precompiled list of vertex attributes.
*/
class IVertexInputLayout : public IDeviceObject<IVertexInputLayout>
{
};
/**
* IShaderProgram is a container for multiple shaders of different types.
*/

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2022 Wildfire Games.
/* Copyright (C) 2023 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -80,6 +80,12 @@ std::unique_ptr<IGraphicsPipelineState> CDevice::CreateGraphicsPipelineState(
return CGraphicsPipelineState::Create(this, pipelineStateDesc);
}
std::unique_ptr<IVertexInputLayout> CDevice::CreateVertexInputLayout(
const PS::span<const SVertexAttributeFormat> UNUSED(attributes))
{
return nullptr;
}
std::unique_ptr<ITexture> CDevice::CreateTexture(
const char* UNUSED(name), const CTexture::Type type, const uint32_t usage,
const Format format, const uint32_t width, const uint32_t height,

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2022 Wildfire Games.
/* Copyright (C) 2023 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -58,6 +58,9 @@ public:
std::unique_ptr<IGraphicsPipelineState> CreateGraphicsPipelineState(
const SGraphicsPipelineStateDesc& pipelineStateDesc) override;
std::unique_ptr<IVertexInputLayout> CreateVertexInputLayout(
const PS::span<const SVertexAttributeFormat> attributes) override;
std::unique_ptr<ITexture> CreateTexture(
const char* name, const ITexture::Type type, const uint32_t usage,
const Format format, const uint32_t width, const uint32_t height,

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2022 Wildfire Games.
/* Copyright (C) 2023 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -128,9 +128,7 @@ void CDeviceCommandContext::SetViewports(const uint32_t, const Rect*)
{
}
void CDeviceCommandContext::SetVertexAttributeFormat(
const VertexAttributeStream, const Format,
const uint32_t, const uint32_t, const VertexAttributeRate, const uint32_t)
void CDeviceCommandContext::SetVertexInputLayout(IVertexInputLayout*)
{
}

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2022 Wildfire Games.
/* Copyright (C) 2023 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -78,13 +78,9 @@ public:
void SetScissors(const uint32_t scissorCount, const Rect* scissors) override;
void SetViewports(const uint32_t viewportCount, const Rect* viewports) override;
void SetVertexAttributeFormat(
const VertexAttributeStream stream,
const Format format,
const uint32_t offset,
const uint32_t stride,
const VertexAttributeRate rate,
const uint32_t bindingSlot) override;
void SetVertexInputLayout(
IVertexInputLayout* vertexInputLayout) override;
void SetVertexBuffer(
const uint32_t bindingSlot, IBuffer* buffer, const uint32_t offset) override;
void SetVertexBufferData(

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2022 Wildfire Games.
/* Copyright (C) 2023 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -875,6 +875,12 @@ std::unique_ptr<IGraphicsPipelineState> CDevice::CreateGraphicsPipelineState(
return CGraphicsPipelineState::Create(this, pipelineStateDesc);
}
std::unique_ptr<IVertexInputLayout> CDevice::CreateVertexInputLayout(
const PS::span<const SVertexAttributeFormat> attributes)
{
return std::make_unique<CVertexInputLayout>(this, attributes);
}
std::unique_ptr<ITexture> CDevice::CreateTexture(
const char* name, const ITexture::Type type, const uint32_t usage,
const Format format, const uint32_t width, const uint32_t height,

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2022 Wildfire Games.
/* Copyright (C) 2023 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -71,6 +71,9 @@ public:
std::unique_ptr<IGraphicsPipelineState> CreateGraphicsPipelineState(
const SGraphicsPipelineStateDesc& pipelineStateDesc) override;
std::unique_ptr<IVertexInputLayout> CreateVertexInputLayout(
const PS::span<const SVertexAttributeFormat> attributes) override;
CDeviceCommandContext* GetActiveCommandContext() { return m_ActiveCommandContext; }
std::unique_ptr<ITexture> CreateTexture(

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2022 Wildfire Games.
/* Copyright (C) 2023 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -968,26 +968,26 @@ void CDeviceCommandContext::SetViewports(const uint32_t viewportCount, const Rec
ogl_WarnIfError();
}
void CDeviceCommandContext::SetVertexAttributeFormat(
const VertexAttributeStream stream,
const Format format,
const uint32_t offset,
const uint32_t stride,
const VertexAttributeRate rate,
const uint32_t bindingSlot)
void CDeviceCommandContext::SetVertexInputLayout(
IVertexInputLayout* vertexInputLayout)
{
const uint32_t index = static_cast<uint32_t>(stream);
ENSURE(index < m_VertexAttributeFormat.size());
ENSURE(bindingSlot < m_VertexAttributeFormat.size());
if (!m_VertexAttributeFormat[index].active)
return;
m_VertexAttributeFormat[index].format = format;
m_VertexAttributeFormat[index].offset = offset;
m_VertexAttributeFormat[index].stride = stride;
m_VertexAttributeFormat[index].rate = rate;
m_VertexAttributeFormat[index].bindingSlot = bindingSlot;
ENSURE(vertexInputLayout);
for (const SVertexAttributeFormat& attribute : vertexInputLayout->As<CVertexInputLayout>()->GetAttributes())
{
const uint32_t index = static_cast<uint32_t>(attribute.stream);
ENSURE(index < m_VertexAttributeFormat.size());
ENSURE(attribute.bindingSlot < m_VertexAttributeFormat.size());
if (!m_VertexAttributeFormat[index].active)
continue;
m_VertexAttributeFormat[index].initialized = true;
m_VertexAttributeFormat[index].format = attribute.format;
m_VertexAttributeFormat[index].offset = attribute.offset;
m_VertexAttributeFormat[index].stride = attribute.stride;
m_VertexAttributeFormat[index].rate = attribute.rate;
m_VertexAttributeFormat[index].bindingSlot = attribute.bindingSlot;
m_VertexAttributeFormat[index].initialized = true;
}
}
void CDeviceCommandContext::SetVertexBuffer(

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2022 Wildfire Games.
/* Copyright (C) 2023 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -87,13 +87,9 @@ public:
void SetScissors(const uint32_t scissorCount, const Rect* scissors) override;
void SetViewports(const uint32_t viewportCount, const Rect* viewports) override;
void SetVertexAttributeFormat(
const VertexAttributeStream stream,
const Format format,
const uint32_t offset,
const uint32_t stride,
const VertexAttributeRate rate,
const uint32_t bindingSlot) override;
void SetVertexInputLayout(
IVertexInputLayout* vertexInputLayout) override;
void SetVertexBuffer(
const uint32_t bindingSlot, IBuffer* buffer, const uint32_t offset) override;
void SetVertexBufferData(

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2022 Wildfire Games.
/* Copyright (C) 2023 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -266,6 +266,11 @@ std::tuple<GLenum, GLenum, GLint> GetElementTypeAndCountFromString(const CStr& s
} // anonymous namespace
IDevice* CVertexInputLayout::GetDevice()
{
return m_Device;
}
#if !CONFIG2_GLES
class CShaderProgramARB final : public CShaderProgram

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2022 Wildfire Games.
/* Copyright (C) 2023 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -20,6 +20,7 @@
#include "lib/ogl.h"
#include "lib/file/vfs/vfs_path.h"
#include "ps/containers/Span.h"
#include "ps/CStrForward.h"
#include "renderer/backend/Format.h"
#include "renderer/backend/gl/Texture.h"
@ -45,6 +46,31 @@ namespace GL
class CDevice;
class CVertexInputLayout : public IVertexInputLayout
{
public:
CVertexInputLayout(CDevice* device, const PS::span<const SVertexAttributeFormat> attributes)
: m_Device(device), m_Attributes(attributes.begin(), attributes.end())
{
for (const SVertexAttributeFormat& attribute : m_Attributes)
{
ENSURE(attribute.format != Format::UNDEFINED);
ENSURE(attribute.stride > 0);
}
}
~CVertexInputLayout() override = default;
IDevice* GetDevice() override;
const std::vector<SVertexAttributeFormat>& GetAttributes() const noexcept { return m_Attributes; }
private:
CDevice* m_Device = nullptr;
std::vector<SVertexAttributeFormat> m_Attributes;
};
/**
* A compiled vertex+fragment shader program.
* The implementation may use GL_ARB_{vertex,fragment}_program (ARB assembly syntax)

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2022 Wildfire Games.
/* Copyright (C) 2023 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -86,6 +86,13 @@ std::unique_ptr<IGraphicsPipelineState> CDevice::CreateGraphicsPipelineState(
return nullptr;
}
std::unique_ptr<IVertexInputLayout> CDevice::CreateVertexInputLayout(
const PS::span<const SVertexAttributeFormat> attributes)
{
UNUSED2(attributes);
return nullptr;
}
std::unique_ptr<ITexture> CDevice::CreateTexture(
const char* name, const ITexture::Type type, const uint32_t usage,
const Format format, const uint32_t width, const uint32_t height,

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2022 Wildfire Games.
/* Copyright (C) 2023 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -59,6 +59,9 @@ public:
std::unique_ptr<IGraphicsPipelineState> CreateGraphicsPipelineState(
const SGraphicsPipelineStateDesc& pipelineStateDesc) override;
std::unique_ptr<IVertexInputLayout> CreateVertexInputLayout(
const PS::span<const SVertexAttributeFormat> attributes) override;
std::unique_ptr<ITexture> CreateTexture(
const char* name, const ITexture::Type type, const uint32_t usage,
const Format format, const uint32_t width, const uint32_t height,