Merge remote-tracking branch 'origin/master' into polybackend

This commit is contained in:
Magnus Norddahl 2019-06-10 22:46:32 +02:00
commit bb47230f79
126 changed files with 2186 additions and 1293 deletions

View file

@ -35,13 +35,61 @@
EXTERN_CVAR(Float, transsouls)
IMPLEMENT_CLASS(DShape2DTransform, false, false)
DEFINE_ACTION_FUNCTION(DShape2DTransform, Clear)
{
PARAM_SELF_PROLOGUE(DShape2DTransform);
self->transform.Identity();
return 0;
}
DEFINE_ACTION_FUNCTION(DShape2DTransform, Rotate)
{
PARAM_SELF_PROLOGUE(DShape2DTransform);
PARAM_FLOAT(angle);
self->transform = DMatrix3x3::Rotate2D(DEG2RAD(angle)) * self->transform;
return 0;
}
DEFINE_ACTION_FUNCTION(DShape2DTransform, Scale)
{
PARAM_SELF_PROLOGUE(DShape2DTransform);
PARAM_FLOAT(x);
PARAM_FLOAT(y);
self->transform = DMatrix3x3::Scale2D(DVector2(x, y)) * self->transform;
return 0;
}
DEFINE_ACTION_FUNCTION(DShape2DTransform, Translate)
{
PARAM_SELF_PROLOGUE(DShape2DTransform);
PARAM_FLOAT(x);
PARAM_FLOAT(y);
self->transform = DMatrix3x3::Translate2D(DVector2(x, y)) * self->transform;
return 0;
}
IMPLEMENT_CLASS(DShape2D, false, false)
DEFINE_ACTION_FUNCTION(DShape2D, SetTransform)
{
PARAM_SELF_PROLOGUE(DShape2D);
PARAM_OBJECT(transform, DShape2DTransform);
self->transform = transform->transform;
self->dirty = true;
return 0;
}
DEFINE_ACTION_FUNCTION(DShape2D, Clear)
{
PARAM_SELF_PROLOGUE(DShape2D);
PARAM_INT(which);
if ( which&C_Verts ) self->mVertices.Clear();
if ( which&C_Verts )
{
self->mVertices.Clear();
self->dirty = true;
}
if ( which&C_Coords ) self->mCoords.Clear();
if ( which&C_Indices ) self->mIndices.Clear();
return 0;
@ -53,6 +101,7 @@ DEFINE_ACTION_FUNCTION(DShape2D, PushVertex)
PARAM_FLOAT(x);
PARAM_FLOAT(y);
self->mVertices.Push(DVector2(x,y));
self->dirty = true;
return 0;
}
@ -380,13 +429,22 @@ void F2DDrawer::AddShape( FTexture *img, DShape2D *shape, DrawParms &parms )
if (!img->isHardwareCanvas() && parms.remap != nullptr && !parms.remap->Inactive)
dg.mTranslation = parms.remap;
if (shape->dirty) {
if (shape->mVertices.Size() != shape->mTransformedVertices.Size())
shape->mTransformedVertices.Resize(shape->mVertices.Size());
for (int i = 0; i < dg.mVertCount; i++) {
shape->mTransformedVertices[i] = (shape->transform * DVector3(shape->mVertices[i], 1.0)).XY();
}
shape->dirty = false;
}
double minx = 16383, miny = 16383, maxx = -16384, maxy = -16384;
for ( int i=0; i<dg.mVertCount; i++ )
{
if ( shape->mVertices[i].X < minx ) minx = shape->mVertices[i].X;
if ( shape->mVertices[i].Y < miny ) miny = shape->mVertices[i].Y;
if ( shape->mVertices[i].X > maxx ) maxx = shape->mVertices[i].X;
if ( shape->mVertices[i].Y > maxy ) maxy = shape->mVertices[i].Y;
if ( shape->mTransformedVertices[i].X < minx ) minx = shape->mTransformedVertices[i].X;
if ( shape->mTransformedVertices[i].Y < miny ) miny = shape->mTransformedVertices[i].Y;
if ( shape->mTransformedVertices[i].X > maxx ) maxx = shape->mTransformedVertices[i].X;
if ( shape->mTransformedVertices[i].Y > maxy ) maxy = shape->mTransformedVertices[i].Y;
}
if (minx < (double)parms.lclip || miny < (double)parms.uclip || maxx >(double)parms.rclip || maxy >(double)parms.dclip)
{
@ -402,7 +460,7 @@ void F2DDrawer::AddShape( FTexture *img, DShape2D *shape, DrawParms &parms )
dg.mVertIndex = (int)mVertices.Reserve(dg.mVertCount);
TwoDVertex *ptr = &mVertices[dg.mVertIndex];
for ( int i=0; i<dg.mVertCount; i++ )
ptr[i].Set(shape->mVertices[i].X, shape->mVertices[i].Y, 0, shape->mCoords[i].X, shape->mCoords[i].Y, vertexcolor);
ptr[i].Set(shape->mTransformedVertices[i].X, shape->mTransformedVertices[i].Y, 0, shape->mCoords[i].X, shape->mCoords[i].Y, vertexcolor);
dg.mIndexIndex = mIndices.Size();
dg.mIndexCount += shape->mIndices.Size();
for ( int i=0; i<int(shape->mIndices.Size()); i+=3 )
@ -485,10 +543,10 @@ void F2DDrawer::AddPoly(FTexture *texture, FVector2 *points, int npoints,
mVertices[poly.mVertIndex+i].Set(points[i].X, points[i].Y, 0, u*uscale, v*vscale, color0);
}
poly.mIndexIndex = mIndices.Size();
poly.mIndexCount += (npoints - 2) * 3;
if (indices == nullptr || indexcount == 0)
{
poly.mIndexCount += (npoints - 2) * 3;
for (int i = 2; i < npoints; ++i)
{
AddIndices(poly.mVertIndex, 3, 0, i - 1, i);
@ -496,10 +554,11 @@ void F2DDrawer::AddPoly(FTexture *texture, FVector2 *points, int npoints,
}
else
{
poly.mIndexCount += (int)indexcount;
int addr = mIndices.Reserve(indexcount);
for (size_t i = 0; i < indexcount; i++)
{
mIndices[addr + i] = addr + indices[i];
mIndices[addr + i] = poly.mVertIndex + indices[i];
}
}

View file

@ -9,6 +9,18 @@
struct DrawParms;
class DShape2DTransform : public DObject
{
DECLARE_CLASS(DShape2DTransform, DObject)
public:
DShape2DTransform()
{
transform.Identity();
}
DMatrix3x3 transform;
};
// intermediate struct for shape drawing
enum EClearWhich
@ -23,9 +35,21 @@ class DShape2D : public DObject
DECLARE_CLASS(DShape2D,DObject)
public:
DShape2D()
{
transform.Identity();
}
TArray<int> mIndices;
TArray<DVector2> mVertices;
TArray<DVector2> mCoords;
DMatrix3x3 transform;
// dirty stores whether we need to re-apply the transformation
// otherwise it uses the cached values
bool dirty = true;
TArray<DVector2> mTransformedVertices;
};
class F2DDrawer

View file

@ -235,7 +235,8 @@ void FGLRenderer::DrawPresentTexture(const IntRect &box, bool applyGamma)
}
mPresentShader->Uniforms->Scale = { screen->mScreenViewport.width / (float)mBuffers->GetWidth(), screen->mScreenViewport.height / (float)mBuffers->GetHeight() };
mPresentShader->Uniforms->Offset = { 0.0f, 0.0f };
mPresentShader->Uniforms.Set();
mPresentShader->Uniforms.SetData();
static_cast<GLDataBuffer*>(mPresentShader->Uniforms.GetBuffer())->BindBase();
RenderScreenQuad();
}

View file

@ -34,6 +34,7 @@
#include "gl/renderer/gl_renderbuffers.h"
#include "gl/renderer/gl_postprocessstate.h"
#include "gl/shaders/gl_shaderprogram.h"
#include "gl/system/gl_buffers.h"
#include <random>
CVAR(Int, gl_multisample, 1, CVAR_ARCHIVE|CVAR_GLOBALCONFIG);
@ -955,7 +956,7 @@ void GLPPRenderState::Draw()
if (!shader->Uniforms)
shader->Uniforms.reset(screen->CreateDataBuffer(POSTPROCESS_BINDINGPOINT, false, false));
shader->Uniforms->SetData(Uniforms.Data.Size(), Uniforms.Data.Data());
shader->Uniforms->BindBase();
static_cast<GLDataBuffer*>(shader->Uniforms.get())->BindBase();
}
// Set shader

View file

@ -58,6 +58,7 @@
#include "r_videoscale.h"
#include "r_data/models/models.h"
#include "gl/renderer/gl_postprocessstate.h"
#include "gl/system/gl_buffers.h"
EXTERN_CVAR(Int, screenblocks)
EXTERN_CVAR(Bool, cl_capfps)
@ -191,12 +192,17 @@ void FGLRenderer::UpdateShadowMap()
FGLPostProcessState savedState;
static_cast<GLDataBuffer*>(screen->mShadowMap.mLightList)->BindBase();
static_cast<GLDataBuffer*>(screen->mShadowMap.mNodesBuffer)->BindBase();
static_cast<GLDataBuffer*>(screen->mShadowMap.mLinesBuffer)->BindBase();
mBuffers->BindShadowMapFB();
mShadowMapShader->Bind();
mShadowMapShader->Uniforms->ShadowmapQuality = gl_shadowmap_quality;
mShadowMapShader->Uniforms->NodesCount = screen->mShadowMap.NodesCount();
mShadowMapShader->Uniforms.Set();
mShadowMapShader->Uniforms.SetData();
static_cast<GLDataBuffer*>(mShadowMapShader->Uniforms.GetBuffer())->BindBase();
glViewport(0, 0, gl_shadowmap_quality, 1024);
RenderScreenQuad();

View file

@ -27,7 +27,7 @@ class FGLRenderBuffers;
class FGL2DDrawer;
class FHardwareTexture;
class SWSceneDrawer;
class GLViewpointBuffer;
class HWViewpointBuffer;
struct FRenderViewpoint;
namespace OpenGLRenderer

View file

@ -189,9 +189,21 @@ bool FGLRenderState::ApplyShader()
matrixToGL(identityMatrix, activeShader->normalmodelmatrix_index);
}
auto index = screen->mLights->BindUBO(mLightIndex);
activeShader->muLightIndex.Set(index);
int index = mLightIndex;
// Mess alert for crappy AncientGL!
if (!screen->mLights->GetBufferType() && index >= 0)
{
size_t start, size;
index = screen->mLights->GetBinding(index, &start, &size);
if (start != mLastMappedLightIndex)
{
mLastMappedLightIndex = start;
static_cast<GLDataBuffer*>(screen->mLights->GetBuffer())->BindRange(nullptr, start, size);
}
}
activeShader->muLightIndex.Set(index);
return true;
}

View file

@ -68,6 +68,7 @@ class FGLRenderState : public FRenderState
int lastClamp = 0;
int lastTranslation = 0;
int maxBoundMaterial = -1;
size_t mLastMappedLightIndex = SIZE_MAX;
IVertexBuffer *mCurrentVertexBuffer;
int mCurrentVertexOffsets[2]; // one per binding point

View file

@ -57,6 +57,7 @@
#include "hwrenderer/scene/hw_portal.h"
#include "hwrenderer/utility/hw_vrmodes.h"
#include "gl/renderer/gl_renderer.h"
#include "gl/system/gl_buffers.h"
//==========================================================================
//

View file

@ -33,6 +33,7 @@
#include "gl/renderer/gl_postprocessstate.h"
#include "gl/system/gl_framebuffer.h"
#include "gl/shaders/gl_shaderprogram.h"
#include "gl/system/gl_buffers.h"
#include "menu/menu.h"
EXTERN_CVAR(Int, vr_mode)
@ -174,7 +175,8 @@ void FGLRenderer::prepareInterleavedPresent(FPresentShaderBase& shader)
screen->mScreenViewport.height / (float)mBuffers->GetHeight()
};
shader.Uniforms->Offset = { 0.0f, 0.0f };
shader.Uniforms.Set();
shader.Uniforms.SetData();
static_cast<GLDataBuffer*>(shader.Uniforms.GetBuffer())->BindBase();
}
//==========================================================================
@ -198,7 +200,8 @@ void FGLRenderer::PresentColumnInterleaved()
int windowHOffset = 0;
mPresent3dColumnShader->Uniforms->WindowPositionParity = windowHOffset;
mPresent3dColumnShader->Uniforms.Set();
mPresent3dColumnShader->Uniforms.SetData();
static_cast<GLDataBuffer*>(mPresent3dColumnShader->Uniforms.GetBuffer())->BindBase();
RenderScreenQuad();
}
@ -225,7 +228,8 @@ void FGLRenderer::PresentRowInterleaved()
+ screen->mOutputLetterbox.height + 1 // +1 because of origin at bottom
) % 2;
mPresent3dRowShader->Uniforms.Set();
mPresent3dRowShader->Uniforms.SetData();
static_cast<GLDataBuffer*>(mPresent3dRowShader->Uniforms.GetBuffer())->BindBase();
RenderScreenQuad();
}
@ -256,7 +260,8 @@ void FGLRenderer::PresentCheckerInterleaved()
+ screen->mOutputLetterbox.height + 1 // +1 because of origin at bottom
) % 2; // because we want the top pixel offset, but gl_FragCoord.y is the bottom pixel offset
mPresent3dCheckerShader->Uniforms.Set();
mPresent3dCheckerShader->Uniforms.SetData();
static_cast<GLDataBuffer*>(mPresent3dCheckerShader->Uniforms.GetBuffer())->BindBase();
RenderScreenQuad();
}

View file

@ -210,10 +210,9 @@ void GLVertexBuffer::Bind(int *offsets)
}
}
void GLDataBuffer::BindRange(size_t start, size_t length)
void GLDataBuffer::BindRange(FRenderState *state, size_t start, size_t length)
{
if (mUseType == GL_UNIFORM_BUFFER) // SSBO's cannot be rebound.
glBindBufferRange(mUseType, mBindingPoint, mBufferId, start, length);
glBindBufferRange(mUseType, mBindingPoint, mBufferId, start, length);
}
void GLDataBuffer::BindBase()

View file

@ -66,8 +66,8 @@ class GLDataBuffer : public IDataBuffer, public GLBuffer
int mBindingPoint;
public:
GLDataBuffer(int bindingpoint, bool is_ssbo) : GLBuffer(is_ssbo? GL_SHADER_STORAGE_BUFFER : GL_UNIFORM_BUFFER), mBindingPoint(bindingpoint) {}
void BindRange(size_t start, size_t length) override;
void BindBase() override;
void BindRange(FRenderState* state, size_t start, size_t length);
void BindBase();
};
}

View file

@ -126,7 +126,7 @@ void OpenGLFrameBuffer::InitializeState()
glslversion = gl.glslversion;
uniformblockalignment = gl.uniformblockalignment;
maxuniformblock = gl.maxuniformblock;
gl_vendorstring = gl.vendorstring;
vendorstring = gl.vendorstring;
if (first)
{
@ -154,12 +154,14 @@ void OpenGLFrameBuffer::InitializeState()
mVertexData = new FFlatVertexBuffer(GetWidth(), GetHeight());
mSkyData = new FSkyVertexBuffer;
mViewpoints = new GLViewpointBuffer;
mViewpoints = new HWViewpointBuffer;
mLights = new FLightBuffer();
GLRenderer = new FGLRenderer(this);
GLRenderer->Initialize(GetWidth(), GetHeight());
static_cast<GLDataBuffer*>(mLights->GetBuffer())->BindBase();
mDebug = std::make_shared<FGLDebug>();
mDebug->Update();
}

View file

@ -177,7 +177,7 @@ void gl_LoadExtensions()
// Mesa implements shader storage only for fragment shaders.
// Just disable the feature there. The light buffer may just use a uniform buffer without any adverse effects.
int v;
int v = 0;
glGetIntegerv(GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS, &v);
if (v == 0)
gl.flags &= ~RFL_SHADER_STORAGE_BUFFER;

View file

@ -3,6 +3,8 @@
#include <stddef.h>
#include <assert.h>
class FRenderState;
// The low level code needs to know which attributes exist.
// OpenGL needs to change the state of all of them per buffer binding.
// VAOs are mostly useless for this because they lump buffer and binding state together which the model code does not want.
@ -76,7 +78,6 @@ class IDataBuffer : virtual public IBuffer
{
// Can be either uniform or shader storage buffer, depending on its needs.
public:
virtual void BindRange(size_t start, size_t length) = 0;
virtual void BindBase() = 0;
virtual void BindRange(FRenderState *state, size_t start, size_t length) = 0;
};

View file

@ -33,7 +33,7 @@
static const int INITIAL_BUFFER_SIZE = 100; // 100 viewpoints per frame should nearly always be enough
GLViewpointBuffer::GLViewpointBuffer()
HWViewpointBuffer::HWViewpointBuffer()
{
mBufferSize = INITIAL_BUFFER_SIZE;
mBlockAlign = ((sizeof(HWViewpointUniforms) / screen->uniformblockalignment) + 1) * screen->uniformblockalignment;
@ -45,13 +45,13 @@ GLViewpointBuffer::GLViewpointBuffer()
mClipPlaneInfo.Push(0);
}
GLViewpointBuffer::~GLViewpointBuffer()
HWViewpointBuffer::~HWViewpointBuffer()
{
delete mBuffer;
}
void GLViewpointBuffer::CheckSize()
void HWViewpointBuffer::CheckSize()
{
if (mUploadIndex >= mBufferSize)
{
@ -62,18 +62,18 @@ void GLViewpointBuffer::CheckSize()
}
}
int GLViewpointBuffer::Bind(FRenderState &di, unsigned int index)
int HWViewpointBuffer::Bind(FRenderState &di, unsigned int index)
{
if (index != mLastMappedIndex)
{
mLastMappedIndex = index;
mBuffer->BindRange(index * mBlockAlign, mBlockAlign);
mBuffer->BindRange(&di, index * mBlockAlign, mBlockAlign);
di.EnableClipDistance(0, mClipPlaneInfo[index]);
}
return index;
}
void GLViewpointBuffer::Set2D(FRenderState &di, int width, int height)
void HWViewpointBuffer::Set2D(FRenderState &di, int width, int height)
{
if (width != m2DWidth || height != m2DHeight)
{
@ -91,7 +91,7 @@ void GLViewpointBuffer::Set2D(FRenderState &di, int width, int height)
Bind(di, 0);
}
int GLViewpointBuffer::SetViewpoint(FRenderState &di, HWViewpointUniforms *vp)
int HWViewpointBuffer::SetViewpoint(FRenderState &di, HWViewpointUniforms *vp)
{
CheckSize();
mBuffer->Map();
@ -102,7 +102,7 @@ int GLViewpointBuffer::SetViewpoint(FRenderState &di, HWViewpointUniforms *vp)
return Bind(di, mUploadIndex++);
}
void GLViewpointBuffer::Clear()
void HWViewpointBuffer::Clear()
{
// Index 0 is reserved for the 2D projection.
mUploadIndex = 1;

View file

@ -5,7 +5,7 @@
struct HWViewpointUniforms;
class FRenderState;
class GLViewpointBuffer
class HWViewpointBuffer
{
IDataBuffer *mBuffer;
@ -24,8 +24,8 @@ class GLViewpointBuffer
public:
GLViewpointBuffer();
~GLViewpointBuffer();
HWViewpointBuffer();
~HWViewpointBuffer();
void Clear();
int Bind(FRenderState &di, unsigned int index);
void Set2D(FRenderState &di, int width, int height);

View file

@ -126,14 +126,16 @@ public:
mBuffer = screen->CreateDataBuffer(bindingpoint, false, false);
}
void Set(bool bind = true)
void SetData()
{
if (mBuffer != nullptr)
mBuffer->SetData(sizeof(T), &Values);
}
// Let's hope this can be done better when things have moved further ahead.
// This really is not the best place to add something that depends on API behavior.
if (bind) mBuffer->BindBase();
IDataBuffer* GetBuffer() const
{
// OpenGL needs to mess around with this in ways that should not be part of the interface.
return mBuffer;
}
T *operator->() { return &Values; }

View file

@ -44,7 +44,7 @@ FLightBuffer::FLightBuffer()
// Hack alert: On Intel's GL driver SSBO's perform quite worse than UBOs.
// We only want to disable using SSBOs for lights but not disable the feature entirely.
// Note that using an uniform buffer here will limit the number of lights per surface so it isn't done for NVidia and AMD.
if (screen->IsVulkan() || ((screen->hwcaps & RFL_SHADER_STORAGE_BUFFER) && !strstr(screen->gl_vendorstring, "Intel")))
if (screen->IsVulkan() || ((screen->hwcaps & RFL_SHADER_STORAGE_BUFFER) && !strstr(screen->vendorstring, "Intel")))
{
mBufferType = true;
mBlockAlign = 0;
@ -74,7 +74,6 @@ FLightBuffer::~FLightBuffer()
void FLightBuffer::Clear()
{
mIndex = 0;
mLastMappedIndex = UINT_MAX;
}
int FLightBuffer::UploadLights(FDynLightData &data)
@ -127,16 +126,13 @@ int FLightBuffer::UploadLights(FDynLightData &data)
}
}
int FLightBuffer::DoBindUBO(unsigned int index)
int FLightBuffer::GetBinding(unsigned int index, size_t* pOffset, size_t* pSize)
{
// this function will only get called if a uniform buffer is used. For a shader storage buffer we only need to bind the buffer once at the start.
unsigned int offset = (index / mBlockAlign) * mBlockAlign;
if (offset != mLastMappedIndex)
{
mLastMappedIndex = offset;
mBuffer->BindRange(offset * ELEMENT_SIZE, mBlockSize * ELEMENT_SIZE);
}
*pOffset = offset * ELEMENT_SIZE;
*pSize = mBlockSize * ELEMENT_SIZE;
return (index - offset);
}

View file

@ -15,7 +15,6 @@ class FLightBuffer
bool mBufferType;
std::atomic<unsigned int> mIndex;
unsigned int mLastMappedIndex;
unsigned int mBlockAlign;
unsigned int mBlockSize;
unsigned int mBufferSize;
@ -34,32 +33,12 @@ public:
void Unmap() { mBuffer->Unmap(); }
unsigned int GetBlockSize() const { return mBlockSize; }
bool GetBufferType() const { return mBufferType; }
int GetBinding(unsigned int index, size_t* pOffset, size_t* pSize);
int DoBindUBO(unsigned int index);
int ShaderIndex(unsigned int index) const
{
if (mBlockAlign == 0) return index;
// This must match the math in BindUBO.
unsigned int offset = (index / mBlockAlign) * mBlockAlign;
return int(index-offset);
}
// Only relevant for OpenGL, so this does not need access to the render state.
int BindUBO(int index)
// OpenGL needs the buffer to mess around with the binding.
IDataBuffer* GetBuffer() const
{
if (!mBufferType && index > -1)
{
index = DoBindUBO(index);
}
return index;
}
// The parameter is a reminder for Vulkan.
void BindBase()
{
mBuffer->BindBase();
mLastMappedIndex = UINT_MAX;
return mBuffer;
}
};

View file

@ -176,9 +176,6 @@ bool IShadowMap::PerformUpdate()
UpdateCycles.Clock();
UploadAABBTree();
UploadLights();
mLightList->BindBase();
mNodesBuffer->BindBase();
mLinesBuffer->BindBase();
return true;
}
return false;

View file

@ -65,6 +65,8 @@ protected:
IShadowMap &operator=(IShadowMap &) = 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.
public:
IDataBuffer *mLightList = nullptr;
// OpenGL storage buffers for the AABB tree

View file

@ -468,7 +468,6 @@ void HWDrawInfo::RenderScene(FRenderState &state)
state.SetDepthMask(true);
screen->mLights->BindBase();
state.EnableFog(true);
state.SetRenderStyle(STYLE_Source);

View file

@ -55,6 +55,7 @@
#include "templates.h"
#include "r_utility.h"
#include "r_renderer.h"
#include "atterm.h"
#include <atomic>
FDynamicColormap NormalLight;

View file

@ -35,7 +35,7 @@ void VkPostprocess::SetActiveRenderTarget()
imageTransition.addImage(&buffers->PipelineImage[mCurrentPipelineImage], VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false);
imageTransition.execute(fb->GetDrawCommands());
fb->GetRenderState()->SetRenderTarget(buffers->PipelineImage[mCurrentPipelineImage].View.get(), nullptr, buffers->GetWidth(), buffers->GetHeight(), VK_FORMAT_R16G16B16A16_SFLOAT, VK_SAMPLE_COUNT_1_BIT);
fb->GetRenderState()->SetRenderTarget(&buffers->PipelineImage[mCurrentPipelineImage], nullptr, buffers->GetWidth(), buffers->GetHeight(), VK_FORMAT_R16G16B16A16_SFLOAT, VK_SAMPLE_COUNT_1_BIT);
}
void VkPostprocess::PostProcessScene(int fixedcm, const std::function<void()> &afterBloomDrawEndScene2D)
@ -402,6 +402,18 @@ VkPPTexture::VkPPTexture(PPTexture *texture)
}
}
VkPPTexture::~VkPPTexture()
{
if (auto fb = GetVulkanFrameBuffer())
{
if (TexImage.Image) fb->FrameDeleteList.Images.push_back(std::move(TexImage.Image));
if (TexImage.View) fb->FrameDeleteList.ImageViews.push_back(std::move(TexImage.View));
if (TexImage.DepthOnlyView) fb->FrameDeleteList.ImageViews.push_back(std::move(TexImage.DepthOnlyView));
if (TexImage.PPFramebuffer) fb->FrameDeleteList.Framebuffers.push_back(std::move(TexImage.PPFramebuffer));
if (Staging) fb->FrameDeleteList.Buffers.push_back(std::move(Staging));
}
}
/////////////////////////////////////////////////////////////////////////////
VkPPShader::VkPPShader(PPShader *shader)
@ -585,6 +597,7 @@ VulkanFramebuffer *VkPPRenderState::GetOutput(VkPPRenderPassSetup *passSetup, co
VkTextureImage *tex = GetTexture(output.Type, output.Texture);
VkImageView view;
std::unique_ptr<VulkanFramebuffer> *framebufferptr = nullptr;
int w, h;
if (tex)
{
@ -597,15 +610,17 @@ VulkanFramebuffer *VkPPRenderState::GetOutput(VkPPRenderPassSetup *passSetup, co
view = tex->View->view;
w = tex->Image->width;
h = tex->Image->height;
framebufferptr = &tex->PPFramebuffer;
}
else
{
view = fb->swapChain->swapChainImageViews[fb->presentImageIndex];
framebufferptr = &fb->swapChain->framebuffers[fb->presentImageIndex];
w = fb->swapChain->actualExtent.width;
h = fb->swapChain->actualExtent.height;
}
auto &framebuffer = passSetup->Framebuffers[view];
auto &framebuffer = *framebufferptr;
if (!framebuffer)
{
FramebufferBuilder builder;

View file

@ -88,6 +88,7 @@ class VkPPTexture : public PPTextureBackend
{
public:
VkPPTexture(PPTexture *texture);
~VkPPTexture();
VkTextureImage TexImage;
std::unique_ptr<VulkanBuffer> Staging;
@ -103,7 +104,6 @@ public:
std::unique_ptr<VulkanPipelineLayout> PipelineLayout;
std::unique_ptr<VulkanRenderPass> RenderPass;
std::unique_ptr<VulkanPipeline> Pipeline;
std::map<VkImageView, std::unique_ptr<VulkanFramebuffer>> Framebuffers;
private:
void CreateDescriptorLayout(const VkPPRenderPassKey &key);

View file

@ -59,7 +59,6 @@ public:
VkRenderPassKey PassKey;
std::unique_ptr<VulkanRenderPass> RenderPasses[8];
std::map<VkPipelineKey, std::unique_ptr<VulkanPipeline>> Pipelines;
std::map<VkImageView, std::unique_ptr<VulkanFramebuffer>> Framebuffer;
private:
std::unique_ptr<VulkanRenderPass> CreateRenderPass(int clearTargets);

View file

@ -528,11 +528,11 @@ void VkRenderState::EnableDrawBuffers(int count)
}
}
void VkRenderState::SetRenderTarget(VulkanImageView *view, VulkanImageView *depthStencilView, int width, int height, VkFormat format, VkSampleCountFlagBits samples)
void VkRenderState::SetRenderTarget(VkTextureImage *image, VulkanImageView *depthStencilView, int width, int height, VkFormat format, VkSampleCountFlagBits samples)
{
EndRenderPass();
mRenderTarget.View = view;
mRenderTarget.Image = image;
mRenderTarget.DepthStencil = depthStencilView;
mRenderTarget.Width = width;
mRenderTarget.Height = height;
@ -552,14 +552,14 @@ void VkRenderState::BeginRenderPass(VulkanCommandBuffer *cmdbuffer)
mPassSetup = fb->GetRenderPassManager()->GetRenderPass(key);
auto &framebuffer = mPassSetup->Framebuffer[mRenderTarget.View->view];
auto &framebuffer = mRenderTarget.Image->RSFramebuffers[key];
if (!framebuffer)
{
auto buffers = fb->GetBuffers();
FramebufferBuilder builder;
builder.setRenderPass(mPassSetup->GetRenderPass(0));
builder.setSize(mRenderTarget.Width, mRenderTarget.Height);
builder.addAttachment(mRenderTarget.View);
builder.addAttachment(mRenderTarget.Image->View.get());
if (key.DrawBuffers > 1)
builder.addAttachment(buffers->SceneFog.View.get());
if (key.DrawBuffers > 2)

View file

@ -12,6 +12,7 @@
#include "hwrenderer/textures/hw_material.h"
class VkRenderPassSetup;
class VkTextureImage;
class VkRenderState : public FRenderState
{
@ -43,7 +44,7 @@ public:
void EnableDrawBuffers(int count) override;
void BeginFrame();
void SetRenderTarget(VulkanImageView *view, VulkanImageView *depthStencilView, int width, int height, VkFormat Format, VkSampleCountFlagBits samples);
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();
@ -112,7 +113,7 @@ protected:
struct RenderTarget
{
VulkanImageView *View = nullptr;
VkTextureImage *Image = nullptr;
VulkanImageView *DepthStencil = nullptr;
int Width = 0;
int Height = 0;

View file

@ -204,12 +204,9 @@ void VKVertexBuffer::SetFormat(int numBindingPoints, int numAttributes, size_t s
/////////////////////////////////////////////////////////////////////////////
void VKDataBuffer::BindRange(size_t start, size_t length)
void VKDataBuffer::BindRange(FRenderState* state, size_t start, size_t length)
{
GetVulkanFrameBuffer()->GetRenderState()->Bind(bindingpoint, (uint32_t)start);
static_cast<VkRenderState*>(state)->Bind(bindingpoint, (uint32_t)start);
}
void VKDataBuffer::BindBase()
{
GetVulkanFrameBuffer()->GetRenderState()->Bind(bindingpoint, 0);
}

View file

@ -68,8 +68,7 @@ public:
}
}
void BindRange(size_t start, size_t length) override;
void BindBase() override;
void BindRange(FRenderState *state, size_t start, size_t length) override;
int bindingpoint;
};

View file

@ -128,7 +128,14 @@ void VulkanFrameBuffer::InitializeState()
first = false;
}
gl_vendorstring = "Vulkan";
switch (device->PhysicalDevice.Properties.vendorID)
{
case 0x1002: vendorstring = "AMD"; break;
case 0x10DE: vendorstring = "NVIDIA"; break;
case 0x8086: vendorstring = "Intel"; break;
default: vendorstring = "Unknown"; break;
}
hwcaps = RFL_SHADER_STORAGE_BUFFER | RFL_BUFFER_STORAGE;
glslversion = 4.50f;
uniformblockalignment = (unsigned int)device->PhysicalDevice.Properties.limits.minUniformBufferOffsetAlignment;
@ -145,7 +152,7 @@ void VulkanFrameBuffer::InitializeState()
mVertexData = new FFlatVertexBuffer(GetWidth(), GetHeight());
mSkyData = new FSkyVertexBuffer;
mViewpoints = new GLViewpointBuffer;
mViewpoints = new HWViewpointBuffer;
mLights = new FLightBuffer();
CreateFanToTrisIndexBuffer();
@ -199,6 +206,7 @@ void VulkanFrameBuffer::DeleteFrameObjects()
{
FrameDeleteList.Images.clear();
FrameDeleteList.ImageViews.clear();
FrameDeleteList.Framebuffers.clear();
FrameDeleteList.Buffers.clear();
FrameDeleteList.Descriptors.clear();
FrameDeleteList.DescriptorPools.clear();
@ -444,7 +452,7 @@ sector_t *VulkanFrameBuffer::RenderViewpoint(FRenderViewpoint &mainvp, AActor *
if (mainview) // Bind the scene frame buffer and turn on draw buffers used by ssao
{
mRenderState->SetRenderTarget(GetBuffers()->SceneColor.View.get(), GetBuffers()->SceneDepthStencil.View.get(), GetBuffers()->GetWidth(), GetBuffers()->GetHeight(), VK_FORMAT_R16G16B16A16_SFLOAT, GetBuffers()->GetSceneSamples());
mRenderState->SetRenderTarget(&GetBuffers()->SceneColor, GetBuffers()->SceneDepthStencil.View.get(), GetBuffers()->GetWidth(), GetBuffers()->GetHeight(), VK_FORMAT_R16G16B16A16_SFLOAT, GetBuffers()->GetSceneSamples());
bool useSSAO = (gl_ssao != 0);
GetRenderState()->SetPassType(useSSAO ? GBUFFER_PASS : NORMAL_PASS);
GetRenderState()->EnableDrawBuffers(GetRenderState()->GetPassDrawBufferCount());
@ -514,7 +522,7 @@ void VulkanFrameBuffer::RenderTextureView(FCanvasTexture *tex, AActor *Viewpoint
barrier0.addImage(image, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, true);
barrier0.execute(GetDrawCommands());
mRenderState->SetRenderTarget(image->View.get(), depthStencil->View.get(), image->Image->width, image->Image->height, VK_FORMAT_R8G8B8A8_UNORM, VK_SAMPLE_COUNT_1_BIT);
mRenderState->SetRenderTarget(image, depthStencil->View.get(), image->Image->width, image->Image->height, VK_FORMAT_R8G8B8A8_UNORM, VK_SAMPLE_COUNT_1_BIT);
IntRect bounds;
bounds.left = bounds.top = 0;
@ -530,7 +538,7 @@ void VulkanFrameBuffer::RenderTextureView(FCanvasTexture *tex, AActor *Viewpoint
barrier1.addImage(image, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, false);
barrier1.execute(GetDrawCommands());
mRenderState->SetRenderTarget(GetBuffers()->SceneColor.View.get(), GetBuffers()->SceneDepthStencil.View.get(), GetBuffers()->GetWidth(), GetBuffers()->GetHeight(), VK_FORMAT_R16G16B16A16_SFLOAT, GetBuffers()->GetSceneSamples());
mRenderState->SetRenderTarget(&GetBuffers()->SceneColor, GetBuffers()->SceneDepthStencil.View.get(), GetBuffers()->GetWidth(), GetBuffers()->GetHeight(), VK_FORMAT_R16G16B16A16_SFLOAT, GetBuffers()->GetSceneSamples());
tex->SetUpdated(true);
}
@ -709,11 +717,12 @@ void VulkanFrameBuffer::UpdatePalette()
FTexture *VulkanFrameBuffer::WipeStartScreen()
{
const auto &viewport = screen->mScreenViewport;
auto tex = new FWrapperTexture(viewport.width, viewport.height, 1);
SetViewportRects(nullptr);
auto tex = new FWrapperTexture(mScreenViewport.width, mScreenViewport.height, 1);
auto systex = static_cast<VkHardwareTexture*>(tex->GetSystemTexture());
systex->CreateWipeTexture(viewport.width, viewport.height, "WipeStartScreen");
systex->CreateWipeTexture(mScreenViewport.width, mScreenViewport.height, "WipeStartScreen");
return tex;
}
@ -724,11 +733,10 @@ FTexture *VulkanFrameBuffer::WipeEndScreen()
Draw2D();
Clear2D();
const auto &viewport = screen->mScreenViewport;
auto tex = new FWrapperTexture(viewport.width, viewport.height, 1);
auto tex = new FWrapperTexture(mScreenViewport.width, mScreenViewport.height, 1);
auto systex = static_cast<VkHardwareTexture*>(tex->GetSystemTexture());
systex->CreateWipeTexture(viewport.width, viewport.height, "WipeEndScreen");
systex->CreateWipeTexture(mScreenViewport.width, mScreenViewport.height, "WipeEndScreen");
return tex;
}

View file

@ -57,6 +57,7 @@ public:
public:
std::vector<std::unique_ptr<VulkanImage>> Images;
std::vector<std::unique_ptr<VulkanImageView>> ImageViews;
std::vector<std::unique_ptr<VulkanFramebuffer>> Framebuffers;
std::vector<std::unique_ptr<VulkanBuffer>> Buffers;
std::vector<std::unique_ptr<VulkanDescriptorSet>> Descriptors;
std::vector<std::unique_ptr<VulkanDescriptorPool>> DescriptorPools;

View file

@ -207,6 +207,7 @@ bool VulkanSwapChain::CreateSwapChain(VkSwapchainKHR oldSwapChain)
void VulkanSwapChain::CreateViews()
{
framebuffers.resize(swapChainImages.size());
swapChainImageViews.reserve(swapChainImages.size());
for (size_t i = 0; i < swapChainImages.size(); i++)
{
@ -335,6 +336,7 @@ void VulkanSwapChain::GetImages()
void VulkanSwapChain::ReleaseViews()
{
framebuffers.clear();
for (auto &view : swapChainImageViews)
{
vkDestroyImageView(device->device, view, nullptr);

View file

@ -4,6 +4,7 @@
class VulkanSemaphore;
class VulkanFence;
class VulkanFramebuffer;
class VulkanSwapChain
{
@ -22,6 +23,7 @@ public:
std::vector<VkImage> swapChainImages;
std::vector<VkImageView> swapChainImageViews;
std::vector<std::unique_ptr<VulkanFramebuffer>> framebuffers;
VkExtent2D actualExtent;

View file

@ -72,8 +72,10 @@ void VkHardwareTexture::Reset()
auto &deleteList = fb->FrameDeleteList;
if (mImage.Image) deleteList.Images.push_back(std::move(mImage.Image));
if (mImage.View) deleteList.ImageViews.push_back(std::move(mImage.View));
for (auto &it : mImage.RSFramebuffers) deleteList.Framebuffers.push_back(std::move(it.second));
if (mDepthStencil.Image) deleteList.Images.push_back(std::move(mDepthStencil.Image));
if (mDepthStencil.View) deleteList.ImageViews.push_back(std::move(mDepthStencil.View));
for (auto &it : mDepthStencil.RSFramebuffers) deleteList.Framebuffers.push_back(std::move(it.second));
mImage.reset();
mDepthStencil.reset();
}
@ -374,5 +376,33 @@ void VkHardwareTexture::CreateWipeTexture(int w, int h, const char *name)
mImage.View = viewbuilder.create(fb->device);
mImage.View->SetDebugName(name);
fb->GetPostprocess()->BlitCurrentToImage(&mImage, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
if (fb->GetBuffers()->GetWidth() > 0 && fb->GetBuffers()->GetHeight() > 0)
{
fb->GetPostprocess()->BlitCurrentToImage(&mImage, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
}
else
{
// hwrenderer asked image data from a frame buffer that was never written into. Let's give it that..
// (ideally the hwrenderer wouldn't do this, but the calling code is too complex for me to fix)
VkImageTransition transition0;
transition0.addImage(&mImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, true);
transition0.execute(fb->GetTransferCommands());
VkImageSubresourceRange range = {};
range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
range.layerCount = 1;
range.levelCount = 1;
VkClearColorValue value = {};
value.float32[0] = 0.0f;
value.float32[1] = 0.0f;
value.float32[2] = 0.0f;
value.float32[3] = 1.0f;
fb->GetTransferCommands()->clearColorImage(mImage.Image->image, mImage.Layout, &value, 1, &range);
VkImageTransition transition1;
transition1.addImage(&mImage, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, false);
transition1.execute(fb->GetTransferCommands());
}
}

View file

@ -3,6 +3,7 @@
#include "vulkan/system/vk_objects.h"
#include "vulkan/system/vk_builders.h"
#include "vulkan/renderer/vk_renderpass.h"
class VkTextureImage
{
@ -23,6 +24,8 @@ public:
std::unique_ptr<VulkanImageView> DepthOnlyView;
VkImageLayout Layout = VK_IMAGE_LAYOUT_UNDEFINED;
VkImageAspectFlags AspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
std::unique_ptr<VulkanFramebuffer> PPFramebuffer;
std::map<VkRenderPassKey, std::unique_ptr<VulkanFramebuffer>> RSFramebuffers;
};
class VkImageTransition