Begin removing binding points from the hwrenderer layer.

Well known buffers should be created and managed by the backend, otherwise the backend just becomes an OpenGL emulator.
This commit is contained in:
Magnus Norddahl 2023-04-16 19:30:27 +02:00 committed by Christoph Oelckers
parent c22c9bea29
commit ae72639853
35 changed files with 265 additions and 238 deletions

View file

@ -80,8 +80,6 @@ public:
virtual void Unmap() {}
void *Memory() { return map; }
size_t Size() { return buffersize; }
virtual void GPUDropSync() {}
virtual void GPUWaitSync() {}
};
class IVertexBuffer : virtual public IBuffer
@ -101,7 +99,4 @@ class IIndexBuffer : virtual public IBuffer
class IDataBuffer : virtual public IBuffer
{
// Can be either uniform or shader storage buffer, depending on its needs.
public:
virtual void BindRange(FRenderState *state, size_t start, size_t length) = 0;
};

View file

@ -45,8 +45,7 @@
//
//==========================================================================
FFlatVertexBuffer::FFlatVertexBuffer(int width, int height, int pipelineNbr):
mPipelineNbr(pipelineNbr)
FFlatVertexBuffer::FFlatVertexBuffer(DFrameBuffer* fb, int width, int height, int pipelineNbr) : fb(fb), mPipelineNbr(pipelineNbr)
{
vbo_shadowdata.Resize(NUM_RESERVED);
@ -79,14 +78,14 @@ FFlatVertexBuffer::FFlatVertexBuffer(int width, int height, int pipelineNbr):
vbo_shadowdata[18].Set(32767.0f, -32767.0f, 32767.0f, 0, 0);
vbo_shadowdata[19].Set(32767.0f, -32767.0f, -32767.0f, 0, 0);
mIndexBuffer = screen->CreateIndexBuffer();
mIndexBuffer = fb->CreateIndexBuffer();
int data[4] = {};
mIndexBuffer->SetData(4, data, BufferUsageType::Static); // On Vulkan this may not be empty, so set some dummy defaults to avoid crashes.
for (int n = 0; n < mPipelineNbr; n++)
{
mVertexBufferPipeline[n] = screen->CreateVertexBuffer();
mVertexBufferPipeline[n] = fb->CreateVertexBuffer();
unsigned int bytesize = BUFFER_SIZE * sizeof(FFlatVertex);
mVertexBufferPipeline[n]->SetData(bytesize, nullptr, BufferUsageType::Persistent);

View file

@ -7,6 +7,7 @@
#include <atomic>
#include <mutex>
class DFrameBuffer;
class FRenderState;
struct secplane_t;
@ -56,6 +57,7 @@ struct FFlatVertex
class FFlatVertexBuffer
{
DFrameBuffer* fb = nullptr;
public:
TArray<FFlatVertex> vbo_shadowdata;
TArray<uint32_t> ibo_data;
@ -90,7 +92,7 @@ public:
NUM_RESERVED = 20
};
FFlatVertexBuffer(int width, int height, int pipelineNbr = 1);
FFlatVertexBuffer(DFrameBuffer* fb, int width, int height, int pipelineNbr = 1);
~FFlatVertexBuffer();
void OutputResized(int width, int height);
@ -139,16 +141,6 @@ public:
mVertexBuffer->Upload(mMapStart * sizeof(FFlatVertex), (mCurIndex - mMapStart) * sizeof(FFlatVertex));
}
void DropSync()
{
mVertexBuffer->GPUDropSync();
}
void WaitSync()
{
mVertexBuffer->GPUWaitSync();
}
int GetPipelinePos()
{
return mPipelinePos;

View file

@ -22,35 +22,35 @@
#include "hw_bonebuffer.h"
#include "hw_dynlightdata.h"
#include "shaderuniforms.h"
#include "v_video.h"
static const int BONE_SIZE = (16*sizeof(float));
BoneBuffer::BoneBuffer(int pipelineNbr) : mPipelineNbr(pipelineNbr)
BoneBuffer::BoneBuffer(DFrameBuffer* fb, int pipelineNbr) : fb(fb), mPipelineNbr(pipelineNbr)
{
int maxNumberOfBones = 80000;
mBufferSize = maxNumberOfBones;
mByteSize = mBufferSize * BONE_SIZE;
if (screen->useSSBO())
//if (fb->useSSBO())
{
mBufferType = true;
mBlockAlign = 0;
mBlockSize = mBufferSize;
mMaxUploadSize = mBlockSize;
}
else
/*else
{
mBufferType = false;
mBlockSize = screen->maxuniformblock / BONE_SIZE;
mBlockAlign = screen->uniformblockalignment < 64 ? 1 : screen->uniformblockalignment / BONE_SIZE;
mBlockSize = fb->maxuniformblock / BONE_SIZE;
mBlockAlign = fb->uniformblockalignment < 64 ? 1 : fb->uniformblockalignment / BONE_SIZE;
mMaxUploadSize = (mBlockSize - mBlockAlign);
}
}*/
for (int n = 0; n < mPipelineNbr; n++)
{
mBufferPipeline[n] = screen->CreateDataBuffer(BONEBUF_BINDINGPOINT, mBufferType, false);
mBufferPipeline[n] = fb->CreateBoneBuffer();
mBufferPipeline[n]->SetData(mByteSize, nullptr, BufferUsageType::Persistent);
}

View file

@ -6,10 +6,12 @@
#include <atomic>
#include <mutex>
class DFrameBuffer;
class FRenderState;
class BoneBuffer
{
DFrameBuffer* fb = nullptr;
IDataBuffer *mBuffer;
IDataBuffer* mBufferPipeline[HW_MAX_PIPELINE_BUFFERS];
int mPipelineNbr;
@ -24,7 +26,7 @@ class BoneBuffer
unsigned int mMaxUploadSize;
public:
BoneBuffer(int pipelineNbr = 1);
BoneBuffer(DFrameBuffer* fb, int pipelineNbr = 1);
~BoneBuffer();
void Clear();

View file

@ -27,40 +27,37 @@
#include "hw_lightbuffer.h"
#include "hw_dynlightdata.h"
#include "shaderuniforms.h"
#include "v_video.h"
static const int ELEMENTS_PER_LIGHT = 4; // each light needs 4 vec4's.
static const int ELEMENT_SIZE = (4*sizeof(float));
FLightBuffer::FLightBuffer(int pipelineNbr):
mPipelineNbr(pipelineNbr)
FLightBuffer::FLightBuffer(DFrameBuffer* fb, int pipelineNbr) : fb(fb), mPipelineNbr(pipelineNbr)
{
int maxNumberOfLights = 80000;
mBufferSize = maxNumberOfLights * ELEMENTS_PER_LIGHT;
mByteSize = mBufferSize * ELEMENT_SIZE;
if (screen->useSSBO())
//if (fb->useSSBO())
{
mBufferType = true;
mBlockAlign = 0;
mBlockSize = mBufferSize;
mMaxUploadSize = mBlockSize;
}
else
/*else
{
mBufferType = false;
mBlockSize = screen->maxuniformblock / ELEMENT_SIZE;
mBlockAlign = screen->uniformblockalignment / ELEMENT_SIZE;
mBlockSize = fb->maxuniformblock / ELEMENT_SIZE;
mBlockAlign = fb->uniformblockalignment / ELEMENT_SIZE;
mMaxUploadSize = (mBlockSize - mBlockAlign);
//mByteSize += screen->maxuniformblock; // to avoid mapping beyond the end of the buffer. REMOVED this...This can try to allocate 100's of MB..
}
}*/
for (int n = 0; n < mPipelineNbr; n++)
{
mBufferPipeline[n] = screen->CreateDataBuffer(LIGHTBUF_BINDINGPOINT, mBufferType, false);
mBufferPipeline[n] = fb->CreateLightBuffer();
mBufferPipeline[n]->SetData(mByteSize, nullptr, BufferUsageType::Persistent);
}

View file

@ -7,10 +7,12 @@
#include <atomic>
#include <mutex>
class DFrameBuffer;
class FRenderState;
class FLightBuffer
{
DFrameBuffer* fb = nullptr;
IDataBuffer *mBuffer;
IDataBuffer* mBufferPipeline[HW_MAX_PIPELINE_BUFFERS];
int mPipelineNbr;
@ -28,7 +30,7 @@ class FLightBuffer
public:
FLightBuffer(int pipelineNbr = 1);
FLightBuffer(DFrameBuffer* fb, int pipelineNbr = 1);
~FLightBuffer();
void Clear();
int UploadLights(FDynLightData &data);

View file

@ -737,6 +737,7 @@ public:
virtual void EnableMultisampling(bool on) = 0; // only active for 2D
virtual void EnableLineSmooth(bool on) = 0; // constant setting for each 2D drawer operation
virtual void EnableDrawBuffers(int count, bool apply = false) = 0; // Used by SSAO and EnableDrawBufferAttachments
virtual void SetViewpointOffset(uint32_t offset) = 0; // HWViewpoint uniform binding offset
void SetColorMask(bool on)
{

View file

@ -24,8 +24,8 @@
#include "hw_cvars.h"
#include "hw_dynlightdata.h"
#include "buffers.h"
#include "shaderuniforms.h"
#include "hwrenderer/postprocessing/hw_postprocess.h"
#include "v_video.h"
/*
The 1D shadow maps are stored in a 1024x1024 texture as float depth values (R32F).
@ -55,9 +55,9 @@
as on the CPU, except everything uses indexes as pointers are not allowed in GLSL.
*/
cycle_t IShadowMap::UpdateCycles;
int IShadowMap::LightsProcessed;
int IShadowMap::LightsShadowmapped;
cycle_t ShadowMap::UpdateCycles;
int ShadowMap::LightsProcessed;
int ShadowMap::LightsShadowmapped;
CVAR(Bool, gl_light_shadowmap, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
CVAR(Bool, gl_light_raytrace, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
@ -65,7 +65,7 @@ CVAR(Bool, gl_light_raytrace, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
ADD_STAT(shadowmap)
{
FString out;
out.Format("upload=%04.2f ms lights=%d shadowmapped=%d", IShadowMap::UpdateCycles.TimeMS(), IShadowMap::LightsProcessed, IShadowMap::LightsShadowmapped);
out.Format("upload=%04.2f ms lights=%d shadowmapped=%d", ShadowMap::UpdateCycles.TimeMS(), ShadowMap::LightsProcessed, ShadowMap::LightsShadowmapped);
return out;
}
@ -84,7 +84,7 @@ CUSTOM_CVAR(Int, gl_shadowmap_quality, 512, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
}
}
bool IShadowMap::ShadowTest(const DVector3 &lpos, const DVector3 &pos)
bool ShadowMap::ShadowTest(const DVector3 &lpos, const DVector3 &pos)
{
if (mAABBTree && gl_light_shadowmap)
return mAABBTree->RayTest(lpos, pos) >= 1.0f;
@ -92,7 +92,7 @@ bool IShadowMap::ShadowTest(const DVector3 &lpos, const DVector3 &pos)
return true;
}
bool IShadowMap::PerformUpdate()
bool ShadowMap::PerformUpdate()
{
UpdateCycles.Reset();
@ -110,30 +110,30 @@ bool IShadowMap::PerformUpdate()
return false;
}
void IShadowMap::UploadLights()
void ShadowMap::UploadLights()
{
mLights.Resize(1024 * 4);
CollectLights();
if (mLightList == nullptr)
mLightList = screen->CreateDataBuffer(LIGHTLIST_BINDINGPOINT, true, false);
mLightList = fb->CreateShadowmapLightsBuffer();
mLightList->SetData(sizeof(float) * mLights.Size(), &mLights[0], BufferUsageType::Stream);
}
void IShadowMap::UploadAABBTree()
void ShadowMap::UploadAABBTree()
{
if (mNewTree)
{
mNewTree = false;
if (!mNodesBuffer)
mNodesBuffer = screen->CreateDataBuffer(LIGHTNODES_BINDINGPOINT, true, false);
mNodesBuffer = fb->CreateShadowmapNodesBuffer();
mNodesBuffer->SetData(mAABBTree->NodesSize(), mAABBTree->Nodes(), BufferUsageType::Static);
if (!mLinesBuffer)
mLinesBuffer = screen->CreateDataBuffer(LIGHTLINES_BINDINGPOINT, true, false);
mLinesBuffer = fb->CreateShadowmapLinesBuffer();
mLinesBuffer->SetData(mAABBTree->LinesSize(), mAABBTree->Lines(), BufferUsageType::Static);
}
else if (mAABBTree->Update())
@ -143,14 +143,14 @@ void IShadowMap::UploadAABBTree()
}
}
void IShadowMap::Reset()
void ShadowMap::Reset()
{
delete mLightList; mLightList = nullptr;
delete mNodesBuffer; mNodesBuffer = nullptr;
delete mLinesBuffer; mLinesBuffer = nullptr;
}
IShadowMap::~IShadowMap()
ShadowMap::~ShadowMap()
{
Reset();
}

View file

@ -7,12 +7,15 @@
#include <functional>
class IDataBuffer;
class DFrameBuffer;
class IShadowMap
class ShadowMap
{
DFrameBuffer* fb = nullptr;
public:
IShadowMap() { }
virtual ~IShadowMap();
ShadowMap(DFrameBuffer* fb) : fb(fb) { }
virtual ~ShadowMap();
void Reset();
@ -75,8 +78,8 @@ protected:
hwrenderer::LevelAABBTree* mAABBTree = nullptr;
bool mNewTree = false;
IShadowMap(const IShadowMap &) = delete;
IShadowMap &operator=(IShadowMap &) = delete;
ShadowMap(const ShadowMap &) = delete;
ShadowMap &operator=(ShadowMap &) = delete;
// OpenGL storage buffer with the list of lights in the shadow map texture
// These buffers need to be accessed by the OpenGL backend directly so that they can be bound.

View file

@ -119,10 +119,10 @@ std::pair<PalEntry, PalEntry>& R_GetSkyCapColor(FGameTexture* tex)
//
//-----------------------------------------------------------------------------
FSkyVertexBuffer::FSkyVertexBuffer()
FSkyVertexBuffer::FSkyVertexBuffer(DFrameBuffer* fb) : fb(fb)
{
CreateDome();
mVertexBuffer = screen->CreateVertexBuffer();
mVertexBuffer = fb->CreateVertexBuffer();
static const FVertexBufferAttribute format[] = {
{ 0, VATTR_VERTEX, VFmt_Float3, (int)myoffsetof(FSkyVertex, x) },

View file

@ -5,6 +5,7 @@
#include "hw_renderstate.h"
#include "skyboxtexture.h"
class DFrameBuffer;
class FGameTexture;
class FRenderState;
class IVertexBuffer;
@ -50,6 +51,7 @@ struct FSkyVertex
class FSkyVertexBuffer
{
friend struct HWSkyPortal;
DFrameBuffer* fb = nullptr;
public:
static const int SKYHEMI_UPPER = 1;
static const int SKYHEMI_LOWER = 2;
@ -81,7 +83,7 @@ public:
public:
FSkyVertexBuffer();
FSkyVertexBuffer(DFrameBuffer* fb);
~FSkyVertexBuffer();
void SetupMatrices(FGameTexture *tex, float x_offset, float y_offset, bool mirror, int mode, VSMatrix &modelmatrix, VSMatrix &textureMatrix, bool tiled, float xscale = 0, float vertscale = 0);
std::pair<IVertexBuffer *, IIndexBuffer *> GetBufferObjects() const

View file

@ -25,24 +25,23 @@
**
**/
#include "hwrenderer/data/shaderuniforms.h"
#include "hw_viewpointuniforms.h"
#include "hw_renderstate.h"
#include "hw_viewpointbuffer.h"
#include "hw_cvars.h"
#include "v_video.h"
static const int INITIAL_BUFFER_SIZE = 100; // 100 viewpoints per frame should nearly always be enough
HWViewpointBuffer::HWViewpointBuffer(int pipelineNbr):
mPipelineNbr(pipelineNbr)
HWViewpointBuffer::HWViewpointBuffer(DFrameBuffer* fb, int pipelineNbr) : fb(fb), mPipelineNbr(pipelineNbr)
{
mBufferSize = INITIAL_BUFFER_SIZE;
mBlockAlign = ((sizeof(HWViewpointUniforms) / screen->uniformblockalignment) + 1) * screen->uniformblockalignment;
mBlockAlign = ((sizeof(HWViewpointUniforms) / fb->uniformblockalignment) + 1) * fb->uniformblockalignment;
mByteSize = mBufferSize * mBlockAlign;
for (int n = 0; n < mPipelineNbr; n++)
{
mBufferPipeline[n] = screen->CreateDataBuffer(VIEWPOINT_BINDINGPOINT, false, true);
mBufferPipeline[n] = fb->CreateViewpointBuffer();
mBufferPipeline[n]->SetData(mByteSize, nullptr, BufferUsageType::Persistent);
}
@ -74,7 +73,7 @@ int HWViewpointBuffer::Bind(FRenderState &di, unsigned int index)
if (index != mLastMappedIndex)
{
mLastMappedIndex = index;
mBuffer->BindRange(&di, index * mBlockAlign, mBlockAlign);
di.SetViewpointOffset(index * mBlockAlign);
di.EnableClipDistance(0, mClipPlaneInfo[index]);
}
return index;

View file

@ -3,10 +3,12 @@
#include "hwrenderer/data/buffers.h"
struct HWViewpointUniforms;
class DFrameBuffer;
class FRenderState;
class HWViewpointBuffer
{
DFrameBuffer* fb = nullptr;
IDataBuffer *mBuffer;
IDataBuffer* mBufferPipeline[HW_MAX_PIPELINE_BUFFERS];
int mPipelineNbr;
@ -25,7 +27,7 @@ class HWViewpointBuffer
public:
HWViewpointBuffer(int pipelineNbr = 1);
HWViewpointBuffer(DFrameBuffer* fb, int pipelineNbr = 1);
~HWViewpointBuffer();
void Clear();
int Bind(FRenderState &di, unsigned int index);

View file

@ -1,95 +0,0 @@
#pragma once
#include <vector>
#include "hwrenderer/data/buffers.h"
#include "v_video.h"
enum
{
LIGHTBUF_BINDINGPOINT = 1,
VIEWPOINT_BINDINGPOINT = 3,
LIGHTNODES_BINDINGPOINT = 4,
LIGHTLINES_BINDINGPOINT = 5,
LIGHTLIST_BINDINGPOINT = 6,
BONEBUF_BINDINGPOINT = 7
};
enum class UniformType
{
Int,
UInt,
Float,
Vec2,
Vec3,
Vec4,
IVec2,
IVec3,
IVec4,
UVec2,
UVec3,
UVec4,
Mat4
};
class UniformFieldDesc
{
public:
UniformFieldDesc() = default;
UniformFieldDesc(const char *name, UniformType type, std::size_t offset) : Name(name), Type(type), Offset(offset) { }
const char *Name;
UniformType Type;
std::size_t Offset;
};
class UniformBlockDecl
{
public:
static FString Create(const char *name, const std::vector<UniformFieldDesc> &fields, int bindingpoint)
{
FString decl;
FString layout;
if (bindingpoint == -1)
{
layout = "push_constant";
}
else if (screen->glslversion < 4.20)
{
layout = "std140";
}
else
{
layout.Format("std140, binding = %d", bindingpoint);
}
decl.Format("layout(%s) uniform %s\n{\n", layout.GetChars(), name);
for (size_t i = 0; i < fields.size(); i++)
{
decl.AppendFormat("\t%s %s;\n", GetTypeStr(fields[i].Type), fields[i].Name);
}
decl += "};\n";
return decl;
}
private:
static const char *GetTypeStr(UniformType type)
{
switch (type)
{
default:
case UniformType::Int: return "int";
case UniformType::UInt: return "uint";
case UniformType::Float: return "float";
case UniformType::Vec2: return "vec2";
case UniformType::Vec3: return "vec3";
case UniformType::Vec4: return "vec4";
case UniformType::IVec2: return "ivec2";
case UniformType::IVec3: return "ivec3";
case UniformType::IVec4: return "ivec4";
case UniformType::UVec2: return "uvec2";
case UniformType::UVec3: return "uvec3";
case UniformType::UVec4: return "uvec4";
case UniformType::Mat4: return "mat4";
}
}
};

View file

@ -882,7 +882,7 @@ void PPShadowMap::Update(PPRenderState* renderstate)
{
ShadowMapUniforms uniforms;
uniforms.ShadowmapQuality = (float)gl_shadowmap_quality;
uniforms.NodesCount = screen->mShadowMap.NodesCount();
uniforms.NodesCount = screen->mShadowMap->NodesCount();
renderstate->PushGroup("shadowmap");

View file

@ -1,15 +1,20 @@
#pragma once
#include "hwrenderer/data/shaderuniforms.h"
#include <memory>
#include <map>
#include "intrect.h"
#include "renderstyle.h"
#include "tarray.h"
#include "zstring.h"
#include "vectors.h"
#include <vector>
struct PostProcessShader;
typedef FRenderStyle PPBlendMode;
typedef IntRect PPViewport;
class FTexture;
class PPTexture;
class PPShader;
@ -24,6 +29,33 @@ enum class ETonemapMode : uint8_t
NumTonemapModes
};
enum class UniformType
{
Int,
UInt,
Float,
Vec2,
Vec3,
Vec4,
IVec2,
IVec3,
IVec4,
UVec2,
UVec3,
UVec4,
Mat4
};
class UniformFieldDesc
{
public:
UniformFieldDesc() = default;
UniformFieldDesc(const char* name, UniformType type, std::size_t offset) : Name(name), Type(type), Offset(offset) { }
const char* Name;
UniformType Type;
std::size_t Offset;
};
enum class PPFilterMode { Nearest, Linear };

View file

@ -145,7 +145,7 @@ public:
HWViewpointBuffer *mViewpoints = nullptr; // Viewpoint render data.
FLightBuffer *mLights = nullptr; // Dynamic lights
BoneBuffer* mBones = nullptr; // Model bones
IShadowMap mShadowMap;
ShadowMap* mShadowMap = nullptr;
int mGameScreenWidth = 0;
int mGameScreenHeight = 0;
@ -166,7 +166,7 @@ public:
virtual bool CompileNextShader() { return true; }
void SetAABBTree(hwrenderer::LevelAABBTree * tree)
{
mShadowMap.SetAABBTree(tree);
mShadowMap->SetAABBTree(tree);
}
virtual void SetLevelMesh(hwrenderer::LevelMesh *mesh) { }
bool allowSSBO() const
@ -236,11 +236,18 @@ public:
virtual void InitLightmap(int LMTextureSize, int LMTextureCount, TArray<uint16_t>& LMTextureData) {}
// Interface to hardware rendering resources
virtual IVertexBuffer *CreateVertexBuffer() { return nullptr; }
virtual IIndexBuffer *CreateIndexBuffer() { return nullptr; }
virtual IDataBuffer *CreateDataBuffer(int bindingpoint, bool ssbo, bool needsresize) { return nullptr; }
virtual IVertexBuffer* CreateVertexBuffer() { return nullptr; }
virtual IIndexBuffer* CreateIndexBuffer() { return nullptr; }
bool BuffersArePersistent() { return !!(hwcaps & RFL_BUFFER_STORAGE); }
// To do: these buffers shouldn't be created by the hwrenderer layer - it will be simpler if the backend manages them completely
virtual IDataBuffer* CreateLightBuffer() { return nullptr; }
virtual IDataBuffer* CreateBoneBuffer() { return nullptr; }
virtual IDataBuffer* CreateViewpointBuffer() { return nullptr; }
virtual IDataBuffer* CreateShadowmapNodesBuffer() { return nullptr; }
virtual IDataBuffer* CreateShadowmapLinesBuffer() { return nullptr; }
virtual IDataBuffer* CreateShadowmapLightsBuffer() { return nullptr; }
// This is overridable in case Vulkan does it differently.
virtual bool RenderTextureIsFlipped() const
{

View file

@ -23,7 +23,7 @@
#include "vk_buffer.h"
#include "vk_hwbuffer.h"
#include "vk_streambuffer.h"
#include "hwrenderer/data/shaderuniforms.h"
#include "vulkan/vk_renderdevice.h"
VkBufferManager::VkBufferManager(VulkanRenderDevice* fb) : fb(fb)
{
@ -74,22 +74,40 @@ IIndexBuffer* VkBufferManager::CreateIndexBuffer()
return new VkHardwareIndexBuffer(fb);
}
IDataBuffer* VkBufferManager::CreateDataBuffer(int bindingpoint, bool ssbo, bool needsresize)
IDataBuffer* VkBufferManager::CreateLightBuffer()
{
auto buffer = new VkHardwareDataBuffer(fb, bindingpoint, ssbo, needsresize);
LightBufferSSO = new VkHardwareDataBuffer(fb, true, false);
return LightBufferSSO;
}
switch (bindingpoint)
{
case LIGHTBUF_BINDINGPOINT: LightBufferSSO = buffer; break;
case VIEWPOINT_BINDINGPOINT: ViewpointUBO = buffer; break;
case LIGHTNODES_BINDINGPOINT: LightNodes = buffer; break;
case LIGHTLINES_BINDINGPOINT: LightLines = buffer; break;
case LIGHTLIST_BINDINGPOINT: LightList = buffer; break;
case BONEBUF_BINDINGPOINT: BoneBufferSSO = buffer; break;
default: break;
}
IDataBuffer* VkBufferManager::CreateBoneBuffer()
{
BoneBufferSSO = new VkHardwareDataBuffer(fb, true, false);
return BoneBufferSSO;
}
return buffer;
IDataBuffer* VkBufferManager::CreateViewpointBuffer()
{
ViewpointUBO = new VkHardwareDataBuffer(fb, false, true);
return ViewpointUBO;
}
IDataBuffer* VkBufferManager::CreateShadowmapNodesBuffer()
{
LightNodes = new VkHardwareDataBuffer(fb, true, false);
return LightNodes;
}
IDataBuffer* VkBufferManager::CreateShadowmapLinesBuffer()
{
LightLines = new VkHardwareDataBuffer(fb, true, false);
return LightLines;
}
IDataBuffer* VkBufferManager::CreateShadowmapLightsBuffer()
{
LightList = new VkHardwareDataBuffer(fb, true, false);
return LightList;
}
void VkBufferManager::CreateFanToTrisIndexBuffer()
@ -110,9 +128,9 @@ void VkBufferManager::CreateFanToTrisIndexBuffer()
VkStreamBuffer::VkStreamBuffer(VkBufferManager* buffers, size_t structSize, size_t count)
{
mBlockSize = static_cast<uint32_t>((structSize + screen->uniformblockalignment - 1) / screen->uniformblockalignment * screen->uniformblockalignment);
mBlockSize = static_cast<uint32_t>((structSize + buffers->fb->uniformblockalignment - 1) / buffers->fb->uniformblockalignment * buffers->fb->uniformblockalignment);
UniformBuffer = (VkHardwareDataBuffer*)buffers->CreateDataBuffer(-1, false, false);
UniformBuffer = new VkHardwareDataBuffer(buffers->fb, false, false);
UniformBuffer->SetData(mBlockSize * count, nullptr, BufferUsageType::Persistent);
}

View file

@ -23,7 +23,13 @@ public:
IVertexBuffer* CreateVertexBuffer();
IIndexBuffer* CreateIndexBuffer();
IDataBuffer* CreateDataBuffer(int bindingpoint, bool ssbo, bool needsresize);
IDataBuffer* CreateLightBuffer();
IDataBuffer* CreateBoneBuffer();
IDataBuffer* CreateViewpointBuffer();
IDataBuffer* CreateShadowmapNodesBuffer();
IDataBuffer* CreateShadowmapLinesBuffer();
IDataBuffer* CreateShadowmapLightsBuffer();
void AddBuffer(VkHardwareBuffer* buffer);
void RemoveBuffer(VkHardwareBuffer* buffer);
@ -46,6 +52,8 @@ private:
VulkanRenderDevice* fb = nullptr;
std::list<VkHardwareBuffer*> Buffers;
friend class VkStreamBuffer;
};
class VkStreamBuffer

View file

@ -243,12 +243,3 @@ void VkHardwareVertexBuffer::SetFormat(int numBindingPoints, int numAttributes,
{
VertexFormat = fb->GetRenderPassManager()->GetVertexFormat(numBindingPoints, numAttributes, stride, attrs);
}
/////////////////////////////////////////////////////////////////////////////
void VkHardwareDataBuffer::BindRange(FRenderState* state, size_t start, size_t length)
{
static_cast<VkRenderState*>(state)->Bind(bindingpoint, (uint32_t)start);
}

View file

@ -59,7 +59,7 @@ public:
class VkHardwareDataBuffer : public IDataBuffer, public VkHardwareBuffer
{
public:
VkHardwareDataBuffer(VulkanRenderDevice* fb, int bindingpoint, bool ssbo, bool needresize) : VkHardwareBuffer(fb), bindingpoint(bindingpoint)
VkHardwareDataBuffer(VulkanRenderDevice* fb, bool ssbo, bool needresize) : VkHardwareBuffer(fb)
{
mBufferType = ssbo ? VK_BUFFER_USAGE_STORAGE_BUFFER_BIT : VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
if (needresize)
@ -67,8 +67,4 @@ public:
mBufferType |= VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
}
}
void BindRange(FRenderState *state, size_t start, size_t length) override;
int bindingpoint;
};

View file

@ -220,9 +220,9 @@ VulkanDescriptorSet* VkDescriptorSetManager::GetInput(VkPPRenderPassSetup* passS
if (bindShadowMapBuffers)
{
write.AddBuffer(descriptors.get(), LIGHTNODES_BINDINGPOINT, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetBufferManager()->LightNodes->mBuffer.get());
write.AddBuffer(descriptors.get(), LIGHTLINES_BINDINGPOINT, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetBufferManager()->LightLines->mBuffer.get());
write.AddBuffer(descriptors.get(), LIGHTLIST_BINDINGPOINT, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetBufferManager()->LightList->mBuffer.get());
write.AddBuffer(descriptors.get(), 4, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetBufferManager()->LightNodes->mBuffer.get());
write.AddBuffer(descriptors.get(), 5, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetBufferManager()->LightLines->mBuffer.get());
write.AddBuffer(descriptors.get(), 6, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetBufferManager()->LightList->mBuffer.get());
}
write.Execute(fb->GetDevice());

View file

@ -341,9 +341,9 @@ void VkPPRenderPassSetup::CreateDescriptorLayout(const VkPPRenderPassKey& key)
builder.AddBinding(i, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
if (key.ShadowMapBuffers)
{
builder.AddBinding(LIGHTNODES_BINDINGPOINT, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
builder.AddBinding(LIGHTLINES_BINDINGPOINT, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
builder.AddBinding(LIGHTLIST_BINDINGPOINT, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
builder.AddBinding(4, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
builder.AddBinding(5, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
builder.AddBinding(6, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
}
builder.DebugName("VkPPRenderPassSetup.DescriptorLayout");
DescriptorLayout = builder.Create(fb->GetDevice());

View file

@ -32,7 +32,7 @@ VkPPShader::VkPPShader(VulkanRenderDevice* fb, PPShader *shader) : fb(fb)
{
FString prolog;
if (!shader->Uniforms.empty())
prolog = UniformBlockDecl::Create("Uniforms", shader->Uniforms, -1);
prolog = CreateUniformBlockDecl("Uniforms", shader->Uniforms, -1);
prolog += shader->Defines;
VertexShader = ShaderBuilder()
@ -79,3 +79,50 @@ FString VkPPShader::LoadShaderCode(const FString &lumpName, const FString &defin
patchedCode << code;
return patchedCode;
}
FString VkPPShader::CreateUniformBlockDecl(const char* name, const std::vector<UniformFieldDesc>& fields, int bindingpoint)
{
FString decl;
FString layout;
if (bindingpoint == -1)
{
layout = "push_constant";
}
else if (screen->glslversion < 4.20)
{
layout = "std140";
}
else
{
layout.Format("std140, binding = %d", bindingpoint);
}
decl.Format("layout(%s) uniform %s\n{\n", layout.GetChars(), name);
for (size_t i = 0; i < fields.size(); i++)
{
decl.AppendFormat("\t%s %s;\n", GetTypeStr(fields[i].Type), fields[i].Name);
}
decl += "};\n";
return decl;
}
const char* VkPPShader::GetTypeStr(UniformType type)
{
switch (type)
{
default:
case UniformType::Int: return "int";
case UniformType::UInt: return "uint";
case UniformType::Float: return "float";
case UniformType::Vec2: return "vec2";
case UniformType::Vec3: return "vec3";
case UniformType::Vec4: return "vec4";
case UniformType::IVec2: return "ivec2";
case UniformType::IVec3: return "ivec3";
case UniformType::IVec4: return "ivec4";
case UniformType::UVec2: return "uvec2";
case UniformType::UVec3: return "uvec3";
case UniformType::UVec4: return "uvec4";
case UniformType::Mat4: return "mat4";
}
}

View file

@ -23,4 +23,6 @@ public:
private:
FString LoadShaderCode(const FString &lumpname, const FString &defines, int version);
static FString CreateUniformBlockDecl(const char* name, const std::vector<UniformFieldDesc>& fields, int bindingpoint);
static const char* GetTypeStr(UniformType type);
};

View file

@ -275,7 +275,7 @@ void VkPostprocess::ClearTonemapPalette()
void VkPostprocess::UpdateShadowMap()
{
if (screen->mShadowMap.PerformUpdate())
if (screen->mShadowMap->PerformUpdate())
{
VkPPRenderState renderstate(fb);
hw_postprocess.shadowmap.Update(&renderstate);
@ -284,7 +284,7 @@ void VkPostprocess::UpdateShadowMap()
.AddImage(&fb->GetTextureManager()->Shadowmap, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, false)
.Execute(fb->GetCommands()->GetDrawCommands());
screen->mShadowMap.FinishUpdate();
screen->mShadowMap->FinishUpdate();
}
}

View file

@ -39,7 +39,6 @@
#include "hw_skydome.h"
#include "hwrenderer/data/hw_viewpointbuffer.h"
#include "flatvertices.h"
#include "hwrenderer/data/shaderuniforms.h"
#include "hw_lightbuffer.h"
#include "hw_bonebuffer.h"
@ -138,7 +137,7 @@ VulkanRenderDevice::~VulkanRenderDevice()
delete mViewpoints;
delete mLights;
delete mBones;
mShadowMap.Reset();
delete mShadowMap;
if (mDescriptorSetManager)
mDescriptorSetManager->Deinit();
@ -192,11 +191,12 @@ void VulkanRenderDevice::InitializeState()
mRenderPassManager.reset(new VkRenderPassManager(this));
mRaytrace.reset(new VkRaytrace(this));
mVertexData = new FFlatVertexBuffer(GetWidth(), GetHeight());
mSkyData = new FSkyVertexBuffer;
mViewpoints = new HWViewpointBuffer;
mLights = new FLightBuffer();
mBones = new BoneBuffer();
mVertexData = new FFlatVertexBuffer(this, GetWidth(), GetHeight());
mSkyData = new FSkyVertexBuffer(this);
mViewpoints = new HWViewpointBuffer(this);
mLights = new FLightBuffer(this);
mBones = new BoneBuffer(this);
mShadowMap = new ShadowMap(this);
mShaderManager.reset(new VkShaderManager(this));
mDescriptorSetManager->Init();
@ -322,9 +322,34 @@ IIndexBuffer *VulkanRenderDevice::CreateIndexBuffer()
return GetBufferManager()->CreateIndexBuffer();
}
IDataBuffer *VulkanRenderDevice::CreateDataBuffer(int bindingpoint, bool ssbo, bool needsresize)
IDataBuffer* VulkanRenderDevice::CreateLightBuffer()
{
return GetBufferManager()->CreateDataBuffer(bindingpoint, ssbo, needsresize);
return GetBufferManager()->CreateLightBuffer();
}
IDataBuffer* VulkanRenderDevice::CreateBoneBuffer()
{
return GetBufferManager()->CreateBoneBuffer();
}
IDataBuffer* VulkanRenderDevice::CreateViewpointBuffer()
{
return GetBufferManager()->CreateViewpointBuffer();
}
IDataBuffer* VulkanRenderDevice::CreateShadowmapNodesBuffer()
{
return GetBufferManager()->CreateShadowmapNodesBuffer();
}
IDataBuffer* VulkanRenderDevice::CreateShadowmapLinesBuffer()
{
return GetBufferManager()->CreateShadowmapLinesBuffer();
}
IDataBuffer* VulkanRenderDevice::CreateShadowmapLightsBuffer()
{
return GetBufferManager()->CreateShadowmapLightsBuffer();
}
void VulkanRenderDevice::SetTextureFilterMode()

View file

@ -74,7 +74,13 @@ public:
FMaterial* CreateMaterial(FGameTexture* tex, int scaleflags) override;
IVertexBuffer *CreateVertexBuffer() override;
IIndexBuffer *CreateIndexBuffer() override;
IDataBuffer *CreateDataBuffer(int bindingpoint, bool ssbo, bool needsresize) override;
IDataBuffer* CreateLightBuffer() override;
IDataBuffer* CreateBoneBuffer() override;
IDataBuffer* CreateViewpointBuffer() override;
IDataBuffer* CreateShadowmapNodesBuffer() override;
IDataBuffer* CreateShadowmapLinesBuffer() override;
IDataBuffer* CreateShadowmapLightsBuffer() override;
FTexture *WipeStartScreen() override;
FTexture *WipeEndScreen() override;

View file

@ -37,7 +37,6 @@
#include "hw_clock.h"
#include "flatvertices.h"
#include "hwrenderer/data/hw_viewpointbuffer.h"
#include "hwrenderer/data/shaderuniforms.h"
CVAR(Int, vk_submit_size, 1000, 0);
EXTERN_CVAR(Bool, r_skipmats)
@ -477,13 +476,10 @@ void VkRenderState::WaitForStreamBuffers()
mMatrixBufferWriter.Reset();
}
void VkRenderState::Bind(int bindingpoint, uint32_t offset)
void VkRenderState::SetViewpointOffset(uint32_t offset)
{
if (bindingpoint == VIEWPOINT_BINDINGPOINT)
{
mViewpointOffset = offset;
mNeedApply = true;
}
mViewpointOffset = offset;
mNeedApply = true;
}
void VkRenderState::BeginFrame()

View file

@ -43,10 +43,10 @@ public:
void EnableMultisampling(bool on) override;
void EnableLineSmooth(bool on) override;
void EnableDrawBuffers(int count, bool apply) override;
void SetViewpointOffset(uint32_t offset) override;
void BeginFrame();
void SetRenderTarget(VkTextureImage *image, VulkanImageView *depthStencilView, int width, int height, VkFormat Format, VkSampleCountFlagBits samples);
void Bind(int bindingpoint, uint32_t offset);
void EndRenderPass();
void EndFrame();

View file

@ -108,7 +108,7 @@ void AddLightToList(FDynLightData &dld, int group, FDynamicLight * light, bool f
}
float shadowIndex;
if (screen->mShadowMap.Enabled()) // note: with shadowmaps switched off, we cannot rely on properly set indices anymore.
if (screen->mShadowMap->Enabled()) // note: with shadowmaps switched off, we cannot rely on properly set indices anymore.
{
shadowIndex = light->mShadowmapIndex + 1.0f;
}

View file

@ -69,16 +69,16 @@ void CleanSWDrawer()
void CollectLights(FLevelLocals* Level)
{
IShadowMap* sm = &screen->mShadowMap;
ShadowMap* sm = screen->mShadowMap;
int lightindex = 0;
// Todo: this should go through the blockmap in a spiral pattern around the player so that closer lights are preferred.
for (auto light = Level->lights; light; light = light->next)
{
IShadowMap::LightsProcessed++;
ShadowMap::LightsProcessed++;
if (light->shadowmapped && light->IsActive() && lightindex < 1024)
{
IShadowMap::LightsShadowmapped++;
ShadowMap::LightsShadowmapped++;
light->mShadowmapIndex = lightindex;
sm->SetLight(lightindex, (float)light->X(), (float)light->Y(), (float)light->Z(), light->GetRadius());
@ -113,7 +113,7 @@ sector_t* RenderViewpoint(FRenderViewpoint& mainvp, AActor* camera, IntRect* bou
if (mainview && toscreen && !(camera->Level->flags3 & LEVEL3_NOSHADOWMAP) && camera->Level->HasDynamicLights && gl_light_shadowmap && screen->allowSSBO() && (screen->hwcaps & RFL_SHADER_STORAGE_BUFFER))
{
screen->SetAABBTree(camera->Level->aabbTree);
screen->mShadowMap.SetCollectLights([=] {
screen->mShadowMap->SetCollectLights([=] {
CollectLights(camera->Level);
});
screen->UpdateShadowMap();
@ -122,7 +122,7 @@ sector_t* RenderViewpoint(FRenderViewpoint& mainvp, AActor* camera, IntRect* bou
{
// null all references to the level if we do not need a shadowmap. This will shortcut all internal calculations without further checks.
screen->SetAABBTree(nullptr);
screen->mShadowMap.SetCollectLights(nullptr);
screen->mShadowMap->SetCollectLights(nullptr);
}
screen->SetLevelMesh(camera->Level->levelMesh);

View file

@ -25,7 +25,7 @@ class HWWall;
class HWFlat;
class HWSprite;
struct HWDecal;
class IShadowMap;
class ShadowMap;
struct particle_t;
struct FDynLightData;
struct HUDSprite;

View file

@ -180,7 +180,7 @@ void HWDrawInfo::GetDynSpriteLight(AActor *self, float x, float y, float z, FLig
frac *= (float)smoothstep(light->pSpotOuterAngle->Cos(), light->pSpotInnerAngle->Cos(), cosDir);
}
if (frac > 0 && (!light->shadowmapped || (light->GetRadius() > 0 && screen->mShadowMap.ShadowTest(light->Pos, { x, y, z }))))
if (frac > 0 && (!light->shadowmapped || (light->GetRadius() > 0 && screen->mShadowMap->ShadowTest(light->Pos, { x, y, z }))))
{
lr = light->GetRed() / 255.0f;
lg = light->GetGreen() / 255.0f;