Skip to content

Commit

Permalink
- move streaming uniform buffers out of VkRenderState
Browse files Browse the repository at this point in the history
  • Loading branch information
dpjudas committed Jul 28, 2019
1 parent 05cae50 commit 4adac3f
Show file tree
Hide file tree
Showing 8 changed files with 227 additions and 88 deletions.
1 change: 1 addition & 0 deletions src/CMakeLists.txt
Expand Up @@ -920,6 +920,7 @@ set (VULKAN_SOURCES
rendering/vulkan/system/vk_buffers.cpp
rendering/vulkan/renderer/vk_renderstate.cpp
rendering/vulkan/renderer/vk_renderpass.cpp
rendering/vulkan/renderer/vk_streambuffer.cpp
rendering/vulkan/renderer/vk_postprocess.cpp
rendering/vulkan/renderer/vk_renderbuffers.cpp
rendering/vulkan/shaders/vk_shader.cpp
Expand Down
4 changes: 2 additions & 2 deletions src/rendering/vulkan/renderer/vk_renderpass.cpp
Expand Up @@ -173,8 +173,8 @@ void VkRenderPassManager::UpdateDynamicSet()
WriteDescriptors update;
update.addBuffer(DynamicSet.get(), 0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, fb->ViewpointUBO->mBuffer.get(), 0, sizeof(HWViewpointUniforms));
update.addBuffer(DynamicSet.get(), 1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->LightBufferSSO->mBuffer.get());
update.addBuffer(DynamicSet.get(), 2, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, fb->MatricesUBO->mBuffer.get(), 0, sizeof(MatricesUBO));
update.addBuffer(DynamicSet.get(), 3, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, fb->StreamUBO->mBuffer.get(), 0, sizeof(StreamUBO));
update.addBuffer(DynamicSet.get(), 2, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, fb->MatrixBuffer->UniformBuffer->mBuffer.get(), 0, sizeof(MatricesUBO));
update.addBuffer(DynamicSet.get(), 3, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, fb->StreamBuffer->UniformBuffer->mBuffer.get(), 0, sizeof(StreamUBO));
update.addCombinedImageSampler(DynamicSet.get(), 4, fb->GetBuffers()->Shadowmap.View.get(), fb->GetBuffers()->ShadowmapSampler.get(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
update.updateSets(fb->device);
}
Expand Down
88 changes: 19 additions & 69 deletions src/rendering/vulkan/renderer/vk_renderstate.cpp
Expand Up @@ -21,7 +21,6 @@ CVAR(Int, vk_submit_size, 1000, 0);

VkRenderState::VkRenderState()
{
mIdentityMatrix.loadIdentity();
Reset();
}

Expand Down Expand Up @@ -322,17 +321,11 @@ void VkRenderState::ApplyStreamData()
else
mStreamData.timer = 0.0f;

mDataIndex++;
if (mDataIndex == MAX_STREAM_DATA)
if (!mStreamBufferWriter.Write(mStreamData))
{
mDataIndex = 0;
mStreamDataOffset += sizeof(StreamUBO);

if (mStreamDataOffset + sizeof(StreamUBO) >= fb->StreamUBO->Size())
WaitForStreamBuffers();
WaitForStreamBuffers();
mStreamBufferWriter.Write(mStreamData);
}
uint8_t *ptr = (uint8_t*)fb->StreamUBO->Memory();
memcpy(ptr + mStreamDataOffset + sizeof(StreamData) * mDataIndex, &mStreamData, sizeof(StreamData));
}

void VkRenderState::ApplyPushConstants()
Expand Down Expand Up @@ -371,63 +364,20 @@ void VkRenderState::ApplyPushConstants()
mPushConstants.uSpecularMaterial = { mMaterial.mMaterial->tex->Glossiness, mMaterial.mMaterial->tex->SpecularLevel };

mPushConstants.uLightIndex = mLightIndex;
mPushConstants.uDataIndex = mDataIndex;
mPushConstants.uDataIndex = mStreamBufferWriter.DataIndex();

auto fb = GetVulkanFrameBuffer();
auto passManager = fb->GetRenderPassManager();
mCommandBuffer->pushConstants(passManager->GetPipelineLayout(mPipelineKey.NumTextureLayers), VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, (uint32_t)sizeof(PushConstants), &mPushConstants);
}

template<typename T>
static void BufferedSet(bool &modified, T &dst, const T &src)
{
if (dst == src)
return;
dst = src;
modified = true;
}

static void BufferedSet(bool &modified, VSMatrix &dst, const VSMatrix &src)
{
if (memcmp(dst.get(), src.get(), sizeof(FLOATTYPE) * 16) == 0)
return;
dst = src;
modified = true;
}

void VkRenderState::ApplyMatrices()
{
bool modified = (mMatricesOffset == 0); // always modified first call
if (mTextureMatrixEnabled)
{
BufferedSet(modified, mMatrices.TextureMatrix, mTextureMatrix);
}
else
{
BufferedSet(modified, mMatrices.TextureMatrix, mIdentityMatrix);
}

if (mModelMatrixEnabled)
{
BufferedSet(modified, mMatrices.ModelMatrix, mModelMatrix);
if (modified)
mMatrices.NormalModelMatrix.computeNormalMatrix(mModelMatrix);
}
else
{
BufferedSet(modified, mMatrices.ModelMatrix, mIdentityMatrix);
BufferedSet(modified, mMatrices.NormalModelMatrix, mIdentityMatrix);
}

if (modified)
auto fb = GetVulkanFrameBuffer();
if (!fb->MatrixBuffer->Write(mModelMatrix, mModelMatrixEnabled, mTextureMatrix, mTextureMatrixEnabled))
{
auto fb = GetVulkanFrameBuffer();

if (mMatricesOffset + (fb->UniformBufferAlignedSize<MatricesUBO>() << 1) >= fb->MatricesUBO->Size())
WaitForStreamBuffers();

mMatricesOffset += fb->UniformBufferAlignedSize<MatricesUBO>();
memcpy(static_cast<uint8_t*>(fb->MatricesUBO->Memory()) + mMatricesOffset, &mMatrices, sizeof(MatricesUBO));
WaitForStreamBuffers();
fb->MatrixBuffer->Write(mModelMatrix, mModelMatrixEnabled, mTextureMatrix, mTextureMatrixEnabled);
}
}

Expand Down Expand Up @@ -470,17 +420,19 @@ void VkRenderState::ApplyMaterial()

void VkRenderState::ApplyDynamicSet()
{
if (mViewpointOffset != mLastViewpointOffset || mMatricesOffset != mLastMatricesOffset || mStreamDataOffset != mLastStreamDataOffset)
auto fb = GetVulkanFrameBuffer();
uint32_t matrixOffset = fb->MatrixBuffer->Offset();
uint32_t streamDataOffset = mStreamBufferWriter.StreamDataOffset();
if (mViewpointOffset != mLastViewpointOffset || matrixOffset != mLastMatricesOffset || streamDataOffset != mLastStreamDataOffset)
{
auto fb = GetVulkanFrameBuffer();
auto passManager = fb->GetRenderPassManager();

uint32_t offsets[3] = { mViewpointOffset, mMatricesOffset, mStreamDataOffset };
uint32_t offsets[3] = { mViewpointOffset, matrixOffset, streamDataOffset };
mCommandBuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, passManager->GetPipelineLayout(mPipelineKey.NumTextureLayers), 0, passManager->DynamicSet.get(), 3, offsets);

mLastViewpointOffset = mViewpointOffset;
mLastMatricesOffset = mMatricesOffset;
mLastStreamDataOffset = mStreamDataOffset;
mLastMatricesOffset = matrixOffset;
mLastStreamDataOffset = streamDataOffset;
}
}

Expand All @@ -489,9 +441,8 @@ void VkRenderState::WaitForStreamBuffers()
EndRenderPass();
GetVulkanFrameBuffer()->WaitForCommands(false);
mApplyCount = 0;
mStreamDataOffset = 0;
mDataIndex = 0;
mMatricesOffset = 0;
mStreamBufferWriter.Reset();
GetVulkanFrameBuffer()->MatrixBuffer->Reset();
}

void VkRenderState::Bind(int bindingpoint, uint32_t offset)
Expand Down Expand Up @@ -527,9 +478,8 @@ void VkRenderState::EndRenderPass()

void VkRenderState::EndFrame()
{
mMatricesOffset = 0;
mStreamDataOffset = 0;
mDataIndex = -1;
GetVulkanFrameBuffer()->MatrixBuffer->Reset();
mStreamBufferWriter.Reset();
}

void VkRenderState::EnableDrawBuffers(int count)
Expand Down
9 changes: 3 additions & 6 deletions src/rendering/vulkan/renderer/vk_renderstate.h
Expand Up @@ -4,6 +4,7 @@
#include "vulkan/system/vk_buffers.h"
#include "vulkan/shaders/vk_shader.h"
#include "vulkan/renderer/vk_renderpass.h"
#include "vulkan/renderer/vk_streambuffer.h"

#include "name.h"

Expand Down Expand Up @@ -63,8 +64,8 @@ class VkRenderState : public FRenderState
void ApplyVertexBuffers();
void ApplyMaterial();

void WaitForStreamBuffers();
void BeginRenderPass(VulkanCommandBuffer *cmdbuffer);
void WaitForStreamBuffers();

bool mDepthClamp = true;
VulkanCommandBuffer *mCommandBuffer = nullptr;
Expand All @@ -90,18 +91,14 @@ class VkRenderState : public FRenderState
int mColorMask = 15;
int mCullMode = 0;

MatricesUBO mMatrices = {};
PushConstants mPushConstants = {};

uint32_t mLastViewpointOffset = 0xffffffff;
uint32_t mLastMatricesOffset = 0xffffffff;
uint32_t mLastStreamDataOffset = 0xffffffff;
uint32_t mViewpointOffset = 0;
uint32_t mMatricesOffset = 0;
uint32_t mDataIndex = -1;
uint32_t mStreamDataOffset = 0;

VSMatrix mIdentityMatrix;
VkStreamBufferWriter mStreamBufferWriter;

int mLastVertexOffsets[2] = { 0, 0 };
IVertexBuffer *mLastVertexBuffer = nullptr;
Expand Down
135 changes: 135 additions & 0 deletions src/rendering/vulkan/renderer/vk_streambuffer.cpp
@@ -0,0 +1,135 @@

#include "vk_renderstate.h"
#include "vulkan/system/vk_framebuffer.h"
#include "vulkan/system/vk_builders.h"
#include "vulkan/renderer/vk_streambuffer.h"

template<typename T>
int UniformBufferAlignedSize(int count) { return ((sizeof(T) + screen->uniformblockalignment - 1) / screen->uniformblockalignment * screen->uniformblockalignment) * count; }

VkStreamBuffer::VkStreamBuffer()
{
auto fb = GetVulkanFrameBuffer();
UniformBuffer = (VKDataBuffer*)fb->CreateDataBuffer(-1, false, false);
UniformBuffer->SetData(UniformBufferAlignedSize<StreamUBO>(200), nullptr, false);
}

VkStreamBuffer::~VkStreamBuffer()
{
delete UniformBuffer;
}

uint32_t VkStreamBuffer::NextStreamDataBlock()
{
mStreamDataOffset += sizeof(StreamUBO);
if (mStreamDataOffset + sizeof(StreamUBO) >= UniformBuffer->Size())
{
mStreamDataOffset = 0;
return 0xffffffff;
}
return mStreamDataOffset;
}

/////////////////////////////////////////////////////////////////////////////

VkStreamBufferWriter::VkStreamBufferWriter()
{
mBuffer = GetVulkanFrameBuffer()->StreamBuffer;
}

bool VkStreamBufferWriter::Write(const StreamData& data)
{
mDataIndex++;
if (mDataIndex == MAX_STREAM_DATA)
{
mDataIndex = 0;
mStreamDataOffset = mBuffer->NextStreamDataBlock();
if (mStreamDataOffset == 0xffffffff)
return false;
}
uint8_t* ptr = (uint8_t*)mBuffer->UniformBuffer->Memory();
memcpy(ptr + mStreamDataOffset + sizeof(StreamData) * mDataIndex, &data, sizeof(StreamData));
return true;
}

void VkStreamBufferWriter::Reset()
{
mDataIndex = MAX_STREAM_DATA - 1;
mStreamDataOffset = 0;
mBuffer->Reset();
}

/////////////////////////////////////////////////////////////////////////////

VkMatrixBuffer::VkMatrixBuffer()
{
mIdentityMatrix.loadIdentity();

auto fb = GetVulkanFrameBuffer();
UniformBuffer = (VKDataBuffer*)fb->CreateDataBuffer(-1, false, false);
UniformBuffer->SetData(UniformBufferAlignedSize<MatricesUBO>(50000), nullptr, false);
}

VkMatrixBuffer::~VkMatrixBuffer()
{
delete UniformBuffer;
}

template<typename T>
static void BufferedSet(bool& modified, T& dst, const T& src)
{
if (dst == src)
return;
dst = src;
modified = true;
}

static void BufferedSet(bool& modified, VSMatrix& dst, const VSMatrix& src)
{
if (memcmp(dst.get(), src.get(), sizeof(FLOATTYPE) * 16) == 0)
return;
dst = src;
modified = true;
}

bool VkMatrixBuffer::Write(const VSMatrix& modelMatrix, bool modelMatrixEnabled, const VSMatrix& textureMatrix, bool textureMatrixEnabled)
{
bool modified = (mOffset == 0); // always modified first call

if (modelMatrixEnabled)
{
BufferedSet(modified, mMatrices.ModelMatrix, modelMatrix);
if (modified)
mMatrices.NormalModelMatrix.computeNormalMatrix(modelMatrix);
}
else
{
BufferedSet(modified, mMatrices.ModelMatrix, mIdentityMatrix);
BufferedSet(modified, mMatrices.NormalModelMatrix, mIdentityMatrix);
}

if (textureMatrixEnabled)
{
BufferedSet(modified, mMatrices.TextureMatrix, textureMatrixEnabled);
}
else
{
BufferedSet(modified, mMatrices.TextureMatrix, mIdentityMatrix);
}

if (modified)
{
if (mOffset + (size_t)UniformBufferAlignedSize<MatricesUBO>(2) >= UniformBuffer->Size())
return false;

mOffset += UniformBufferAlignedSize<MatricesUBO>(1);
memcpy(static_cast<uint8_t*>(UniformBuffer->Memory()) + mOffset, &mMatrices, sizeof(MatricesUBO));
}

return true;
}

void VkMatrixBuffer::Reset()
{
mOffset = 0;
}
58 changes: 58 additions & 0 deletions src/rendering/vulkan/renderer/vk_streambuffer.h
@@ -0,0 +1,58 @@

#pragma once

#include "vulkan/system/vk_buffers.h"
#include "vulkan/shaders/vk_shader.h"

class VkStreamBuffer;

class VkStreamBufferWriter
{
public:
VkStreamBufferWriter();

bool Write(const StreamData& data);
void Reset();

uint32_t DataIndex() const { return mDataIndex; }
uint32_t StreamDataOffset() const { return mStreamDataOffset; }

private:
VkStreamBuffer* mBuffer;
uint32_t mDataIndex = MAX_STREAM_DATA - 1;
uint32_t mStreamDataOffset = 0;
};

class VkStreamBuffer
{
public:
VkStreamBuffer();
~VkStreamBuffer();

uint32_t NextStreamDataBlock();
void Reset() { mStreamDataOffset = 0; }

VKDataBuffer* UniformBuffer = nullptr;

private:
uint32_t mStreamDataOffset = 0;
};

class VkMatrixBuffer
{
public:
VkMatrixBuffer();
~VkMatrixBuffer();

bool Write(const VSMatrix &modelMatrix, bool modelMatrixEnabled, const VSMatrix& textureMatrix, bool textureMatrixEnabled);
void Reset();

uint32_t Offset() const { return mOffset; }

VKDataBuffer* UniformBuffer = nullptr;

private:
MatricesUBO mMatrices = {};
VSMatrix mIdentityMatrix;
uint32_t mOffset = 0;
};

0 comments on commit 4adac3f

Please sign in to comment.