Fix in-flight frame update Vulkan (#3122)
This commit is contained in:
@@ -51,14 +51,18 @@ public:
|
||||
void update(const void* data, std::size_t size, std::size_t offset) noexcept;
|
||||
|
||||
std::size_t getSizeInBytes() const noexcept { return size; }
|
||||
const void* contents() const noexcept { return (raw.empty() ? nullptr : raw.data()); }
|
||||
const void* contents() const noexcept;
|
||||
const void* contents(uint8_t resourceIndex) const noexcept;
|
||||
|
||||
Context& getContext() const noexcept { return context; }
|
||||
const vk::Buffer& getVulkanBuffer() const noexcept { return bufferAllocation->buffer; }
|
||||
std::size_t getVulkanBufferOffset() const noexcept;
|
||||
std::size_t getVulkanBufferSize() const noexcept;
|
||||
std::size_t getVulkanBufferOffset(uint8_t resourceIndex) const noexcept;
|
||||
// update the current sub-buffer with the latest data
|
||||
void updateVulkanBuffer();
|
||||
void updateVulkanBuffer(const int8_t destination, const uint8_t source);
|
||||
|
||||
bool isValid() const noexcept { return !raw.empty(); }
|
||||
bool isValid() const noexcept { return !!bufferAllocation; }
|
||||
operator bool() const noexcept { return isValid(); }
|
||||
bool operator!() const noexcept { return !isValid(); }
|
||||
|
||||
@@ -69,14 +73,14 @@ public:
|
||||
|
||||
protected:
|
||||
Context& context;
|
||||
std::vector<std::uint8_t> raw;
|
||||
std::size_t size;
|
||||
std::uint32_t usage;
|
||||
std::uint16_t version = 0;
|
||||
VersionType version = 0;
|
||||
bool persistent;
|
||||
|
||||
SharedBufferAllocation bufferAllocation;
|
||||
size_t bufferWindowSize = 0;
|
||||
std::vector<VersionType> bufferWindowVersions;
|
||||
};
|
||||
|
||||
} // namespace vulkan
|
||||
|
||||
@@ -136,9 +136,7 @@ public:
|
||||
RenderStaticData& staticData,
|
||||
const std::vector<shaders::ClipUBO>& tileUBOs);
|
||||
|
||||
const std::unique_ptr<BufferResource>& getDummyVertexBuffer();
|
||||
const std::unique_ptr<BufferResource>& getDummyUniformBuffer();
|
||||
const std::unique_ptr<BufferResource>& getDummyStorageBuffer();
|
||||
const std::unique_ptr<BufferResource>& getDummyBuffer();
|
||||
const std::unique_ptr<Texture2D>& getDummyTexture();
|
||||
|
||||
const vk::DescriptorSetLayout& getDescriptorSetLayout(DescriptorSetType type);
|
||||
@@ -190,9 +188,7 @@ private:
|
||||
vulkan::UniformBufferArray globalUniformBuffers;
|
||||
std::unordered_map<DescriptorSetType, DescriptorPoolGrowable> descriptorPoolMap;
|
||||
|
||||
std::unique_ptr<BufferResource> dummyVertexBuffer;
|
||||
std::unique_ptr<BufferResource> dummyUniformBuffer;
|
||||
std::unique_ptr<BufferResource> dummyStorageBuffer;
|
||||
std::unique_ptr<BufferResource> dummyBuffer;
|
||||
std::unique_ptr<Texture2D> dummyTexture2D;
|
||||
vk::UniqueDescriptorSetLayout globalUniformDescriptorSetLayout;
|
||||
vk::UniqueDescriptorSetLayout layerUniformDescriptorSetLayout;
|
||||
|
||||
@@ -70,6 +70,8 @@ public:
|
||||
|
||||
void startFrameCapture();
|
||||
void endFrameCapture();
|
||||
void setFrameCaptureLoop(bool value);
|
||||
void triggerFrameCapture(uint32_t frameCount = 1, uint32_t frameDelay = 0);
|
||||
|
||||
protected:
|
||||
std::unique_ptr<gfx::Context> createContext() override;
|
||||
|
||||
@@ -15,6 +15,7 @@ public:
|
||||
~UniformBuffer() override;
|
||||
|
||||
const BufferResource& getBufferResource() const { return buffer; }
|
||||
BufferResource& mutableBufferResource() { return buffer; }
|
||||
|
||||
UniformBuffer clone() const { return {buffer.clone()}; }
|
||||
|
||||
@@ -37,14 +38,21 @@ public:
|
||||
descriptorStorageCount(descriptorStorageCount_),
|
||||
descriptorUniformCount(descriptorUniformCount_) {}
|
||||
|
||||
UniformBufferArray(UniformBufferArray&& other)
|
||||
: gfx::UniformBufferArray(std::move(other)) {}
|
||||
UniformBufferArray(UniformBufferArray&& other) noexcept
|
||||
: gfx::UniformBufferArray(std::move(other)),
|
||||
descriptorSetType(other.descriptorSetType),
|
||||
descriptorStartIndex(other.descriptorStartIndex),
|
||||
descriptorStorageCount(other.descriptorStorageCount),
|
||||
descriptorUniformCount(other.descriptorUniformCount),
|
||||
descriptorSet(std::move(other.descriptorSet)) {}
|
||||
|
||||
UniformBufferArray(const UniformBufferArray&) = delete;
|
||||
|
||||
UniformBufferArray& operator=(UniformBufferArray&& other) {
|
||||
UniformBufferArray& operator=(UniformBufferArray&& other) noexcept {
|
||||
gfx::UniformBufferArray::operator=(std::move(other));
|
||||
return *this;
|
||||
}
|
||||
|
||||
UniformBufferArray& operator=(const UniformBufferArray& other) {
|
||||
gfx::UniformBufferArray::operator=(other);
|
||||
return *this;
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <mbgl/util/instrumentation.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <numeric>
|
||||
|
||||
namespace mbgl {
|
||||
namespace vulkan {
|
||||
@@ -59,12 +60,25 @@ BufferResource::BufferResource(
|
||||
if (usage & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT || usage & VK_BUFFER_USAGE_STORAGE_BUFFER_BIT) {
|
||||
const auto& backend = context.getBackend();
|
||||
const auto& deviceProps = backend.getDeviceProperties();
|
||||
const auto& align = deviceProps.limits.minUniformBufferOffsetAlignment;
|
||||
|
||||
vk::DeviceSize align = 0;
|
||||
if (usage & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT) {
|
||||
align = deviceProps.limits.minUniformBufferOffsetAlignment;
|
||||
}
|
||||
|
||||
if (usage & VK_BUFFER_USAGE_STORAGE_BUFFER_BIT) {
|
||||
align = align ? std::lcm(align, deviceProps.limits.minStorageBufferOffsetAlignment)
|
||||
: deviceProps.limits.minStorageBufferOffsetAlignment;
|
||||
}
|
||||
|
||||
bufferWindowSize = (size + align - 1) & ~(align - 1);
|
||||
|
||||
assert(bufferWindowSize != 0);
|
||||
|
||||
totalSize = bufferWindowSize * backend.getMaxFrames();
|
||||
const auto frameCount = backend.getMaxFrames();
|
||||
totalSize = bufferWindowSize * frameCount;
|
||||
|
||||
bufferWindowVersions = std::vector<std::uint16_t>(frameCount, 0);
|
||||
}
|
||||
|
||||
const auto bufferInfo = vk::BufferCreateInfo()
|
||||
@@ -87,9 +101,7 @@ BufferResource::BufferResource(
|
||||
vmaMapMemory(allocator, bufferAllocation->allocation, &bufferAllocation->mappedBuffer);
|
||||
|
||||
if (data) {
|
||||
raw.resize(size);
|
||||
std::memcpy(raw.data(), data, size);
|
||||
std::memcpy(static_cast<uint8_t*>(bufferAllocation->mappedBuffer) + getVulkanBufferOffset(), data, size);
|
||||
update(data, size, 0);
|
||||
}
|
||||
|
||||
if (isValid()) {
|
||||
@@ -104,12 +116,13 @@ BufferResource::BufferResource(
|
||||
|
||||
BufferResource::BufferResource(BufferResource&& other) noexcept
|
||||
: context(other.context),
|
||||
raw(std::move(other.raw)),
|
||||
size(other.size),
|
||||
usage(other.usage),
|
||||
version(other.version),
|
||||
persistent(other.persistent),
|
||||
bufferAllocation(std::move(other.bufferAllocation)),
|
||||
bufferWindowSize(other.bufferWindowSize) {
|
||||
bufferWindowSize(other.bufferWindowSize),
|
||||
bufferWindowVersions(std::move(other.bufferWindowVersions)) {
|
||||
other.bufferAllocation = nullptr;
|
||||
}
|
||||
|
||||
@@ -134,7 +147,7 @@ BufferResource& BufferResource::operator=(BufferResource&& other) noexcept {
|
||||
context.renderingStats().numBuffers--;
|
||||
context.renderingStats().memBuffers -= size;
|
||||
};
|
||||
raw = std::move(other.raw);
|
||||
|
||||
size = other.size;
|
||||
usage = other.usage;
|
||||
persistent = other.persistent;
|
||||
@@ -152,21 +165,63 @@ void BufferResource::update(const void* newData, std::size_t updateSize, std::si
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t* data = static_cast<uint8_t*>(bufferAllocation->mappedBuffer) + getVulkanBufferOffset() + offset;
|
||||
std::memcpy(data, newData, updateSize);
|
||||
|
||||
auto& stats = context.renderingStats();
|
||||
|
||||
std::memcpy(raw.data() + offset, newData, updateSize);
|
||||
std::memcpy(
|
||||
static_cast<uint8_t*>(bufferAllocation->mappedBuffer) + getVulkanBufferOffset() + offset, newData, updateSize);
|
||||
stats.bufferUpdateBytes += updateSize;
|
||||
|
||||
stats.bufferUpdates++;
|
||||
version++;
|
||||
|
||||
if (bufferWindowSize) {
|
||||
const auto frameIndex = context.getCurrentFrameResourceIndex();
|
||||
bufferWindowVersions[frameIndex] = version;
|
||||
}
|
||||
}
|
||||
|
||||
const void* BufferResource::contents() const noexcept {
|
||||
return contents(context.getCurrentFrameResourceIndex());
|
||||
}
|
||||
|
||||
const void* BufferResource::contents(uint8_t resourceIndex) const noexcept {
|
||||
if (!isValid()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return static_cast<uint8_t*>(bufferAllocation->mappedBuffer) + getVulkanBufferOffset(resourceIndex);
|
||||
}
|
||||
|
||||
std::size_t BufferResource::getVulkanBufferOffset() const noexcept {
|
||||
if (bufferWindowSize > 0) return 0;
|
||||
return getVulkanBufferOffset(context.getCurrentFrameResourceIndex());
|
||||
}
|
||||
|
||||
return context.getCurrentFrameResourceIndex() * bufferWindowSize;
|
||||
std::size_t BufferResource::getVulkanBufferOffset(std::uint8_t resourceIndex) const noexcept {
|
||||
assert(context.getBackend().getMaxFrames() >= resourceIndex);
|
||||
return bufferWindowSize ? resourceIndex * bufferWindowSize : 0;
|
||||
}
|
||||
|
||||
void BufferResource::updateVulkanBuffer() {
|
||||
const auto frameCount = context.getBackend().getMaxFrames();
|
||||
|
||||
const int8_t currentIndex = context.getCurrentFrameResourceIndex();
|
||||
const int8_t prevIndex = currentIndex == 0 ? frameCount - 1 : currentIndex - 1;
|
||||
|
||||
updateVulkanBuffer(currentIndex, prevIndex);
|
||||
}
|
||||
|
||||
void BufferResource::updateVulkanBuffer(const int8_t destination, const uint8_t source) {
|
||||
if (!bufferWindowSize) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (bufferWindowVersions[destination] < bufferWindowVersions[source]) {
|
||||
uint8_t* dstData = static_cast<uint8_t*>(bufferAllocation->mappedBuffer) + bufferWindowSize * destination;
|
||||
uint8_t* srcData = static_cast<uint8_t*>(bufferAllocation->mappedBuffer) + bufferWindowSize * source;
|
||||
|
||||
std::memcpy(dstData, srcData, size);
|
||||
|
||||
bufferWindowVersions[destination] = bufferWindowVersions[source];
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace vulkan
|
||||
|
||||
@@ -563,25 +563,14 @@ bool Context::renderTileClippingMasks(gfx::RenderPass& renderPass,
|
||||
return true;
|
||||
}
|
||||
|
||||
const std::unique_ptr<BufferResource>& Context::getDummyVertexBuffer() {
|
||||
if (!dummyVertexBuffer)
|
||||
dummyVertexBuffer = std::make_unique<BufferResource>(
|
||||
*this, nullptr, 16, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, false);
|
||||
return dummyVertexBuffer;
|
||||
}
|
||||
const std::unique_ptr<BufferResource>& Context::getDummyBuffer() {
|
||||
if (!dummyBuffer) {
|
||||
const uint32_t usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT |
|
||||
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
|
||||
dummyBuffer = std::make_unique<BufferResource>(*this, nullptr, 16, usage, false);
|
||||
}
|
||||
|
||||
const std::unique_ptr<BufferResource>& Context::getDummyUniformBuffer() {
|
||||
if (!dummyUniformBuffer)
|
||||
dummyUniformBuffer = std::make_unique<BufferResource>(
|
||||
*this, nullptr, 16, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, false);
|
||||
return dummyUniformBuffer;
|
||||
}
|
||||
|
||||
const std::unique_ptr<BufferResource>& Context::getDummyStorageBuffer() {
|
||||
if (!dummyStorageBuffer)
|
||||
dummyStorageBuffer = std::make_unique<BufferResource>(
|
||||
*this, nullptr, 16, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, false);
|
||||
return dummyStorageBuffer;
|
||||
return dummyBuffer;
|
||||
}
|
||||
|
||||
const std::unique_ptr<Texture2D>& Context::getDummyTexture() {
|
||||
|
||||
@@ -165,8 +165,7 @@ void UniformDescriptorSet::update(const gfx::UniformBufferArray& uniforms,
|
||||
.setOffset(bufferResource.getVulkanBufferOffset())
|
||||
.setRange(bufferResource.getSizeInBytes());
|
||||
} else {
|
||||
const auto& dummyBuffer = index < descriptorStorageCount ? context.getDummyStorageBuffer()
|
||||
: context.getDummyUniformBuffer();
|
||||
const auto& dummyBuffer = context.getDummyBuffer();
|
||||
descriptorBufferInfo.setBuffer(dummyBuffer->getVulkanBuffer()).setOffset(0).setRange(VK_WHOLE_SIZE);
|
||||
}
|
||||
|
||||
|
||||
@@ -219,7 +219,8 @@ void SurfaceRenderableResource::initDepthStencil() {
|
||||
.setViewType(vk::ImageViewType::e2D)
|
||||
.setFormat(depthFormat)
|
||||
.setComponents(vk::ComponentMapping()) // defaults to vk::ComponentSwizzle::eIdentity
|
||||
.setSubresourceRange(vk::ImageSubresourceRange(vk::ImageAspectFlagBits::eDepth, 0, 1, 0, 1));
|
||||
.setSubresourceRange(vk::ImageSubresourceRange(
|
||||
vk::ImageAspectFlagBits::eDepth | vk::ImageAspectFlagBits::eStencil, 0, 1, 0, 1));
|
||||
|
||||
depthAllocation->imageView = device->createImageViewUnique(imageViewCreateInfo);
|
||||
|
||||
@@ -307,28 +308,29 @@ void SurfaceRenderableResource::init(uint32_t w, uint32_t h) {
|
||||
|
||||
// create render pass
|
||||
const auto colorLayout = surface ? vk::ImageLayout::ePresentSrcKHR : vk::ImageLayout::eTransferSrcOptimal;
|
||||
const auto colorAttachment = vk::AttachmentDescription(vk::AttachmentDescriptionFlags())
|
||||
.setFormat(colorFormat)
|
||||
.setSamples(vk::SampleCountFlagBits::e1)
|
||||
.setLoadOp(vk::AttachmentLoadOp::eClear)
|
||||
.setStoreOp(vk::AttachmentStoreOp::eStore)
|
||||
.setStencilLoadOp(vk::AttachmentLoadOp::eDontCare)
|
||||
.setStencilStoreOp(vk::AttachmentStoreOp::eDontCare)
|
||||
.setInitialLayout(vk::ImageLayout::eUndefined)
|
||||
.setFinalLayout(colorLayout);
|
||||
|
||||
const std::array<vk::AttachmentDescription, 2> attachments = {
|
||||
vk::AttachmentDescription()
|
||||
.setFormat(colorFormat)
|
||||
.setSamples(vk::SampleCountFlagBits::e1)
|
||||
.setLoadOp(vk::AttachmentLoadOp::eClear)
|
||||
.setStoreOp(vk::AttachmentStoreOp::eStore)
|
||||
.setStencilLoadOp(vk::AttachmentLoadOp::eDontCare)
|
||||
.setStencilStoreOp(vk::AttachmentStoreOp::eDontCare)
|
||||
.setInitialLayout(vk::ImageLayout::eUndefined)
|
||||
.setFinalLayout(colorLayout),
|
||||
|
||||
vk::AttachmentDescription()
|
||||
.setFormat(depthFormat)
|
||||
.setSamples(vk::SampleCountFlagBits::e1)
|
||||
.setLoadOp(vk::AttachmentLoadOp::eClear)
|
||||
.setStoreOp(vk::AttachmentStoreOp::eDontCare)
|
||||
.setStencilLoadOp(vk::AttachmentLoadOp::eClear)
|
||||
.setStencilStoreOp(vk::AttachmentStoreOp::eDontCare)
|
||||
.setInitialLayout(vk::ImageLayout::eUndefined)
|
||||
.setFinalLayout(vk::ImageLayout::eDepthStencilAttachmentOptimal)};
|
||||
|
||||
const vk::AttachmentReference colorAttachmentRef(0, vk::ImageLayout::eColorAttachmentOptimal);
|
||||
|
||||
const auto depthAttachment = vk::AttachmentDescription()
|
||||
.setFormat(depthFormat)
|
||||
.setSamples(vk::SampleCountFlagBits::e1)
|
||||
.setLoadOp(vk::AttachmentLoadOp::eClear)
|
||||
.setStoreOp(vk::AttachmentStoreOp::eDontCare)
|
||||
.setStencilLoadOp(vk::AttachmentLoadOp::eClear)
|
||||
.setStencilStoreOp(vk::AttachmentStoreOp::eDontCare)
|
||||
.setInitialLayout(vk::ImageLayout::eUndefined)
|
||||
.setFinalLayout(vk::ImageLayout::eDepthStencilAttachmentOptimal);
|
||||
|
||||
const vk::AttachmentReference depthAttachmentRef(1, vk::ImageLayout::eDepthStencilAttachmentOptimal);
|
||||
|
||||
const auto subpass = vk::SubpassDescription()
|
||||
@@ -337,28 +339,28 @@ void SurfaceRenderableResource::init(uint32_t w, uint32_t h) {
|
||||
.setColorAttachments(colorAttachmentRef)
|
||||
.setPDepthStencilAttachment(&depthAttachmentRef);
|
||||
|
||||
const auto subpassSrcStageMask = vk::PipelineStageFlags() | vk::PipelineStageFlagBits::eColorAttachmentOutput |
|
||||
vk::PipelineStageFlagBits::eLateFragmentTests;
|
||||
const std::array<vk::SubpassDependency, 2> dependencies = {
|
||||
vk::SubpassDependency()
|
||||
.setSrcSubpass(VK_SUBPASS_EXTERNAL)
|
||||
.setDstSubpass(0)
|
||||
.setSrcStageMask(vk::PipelineStageFlagBits::eColorAttachmentOutput)
|
||||
.setDstStageMask(vk::PipelineStageFlagBits::eColorAttachmentOutput)
|
||||
.setSrcAccessMask({})
|
||||
.setDstAccessMask(vk::AccessFlagBits::eColorAttachmentWrite),
|
||||
|
||||
const auto subpassDstStageMask = vk::PipelineStageFlags() | vk::PipelineStageFlagBits::eColorAttachmentOutput |
|
||||
vk::PipelineStageFlagBits::eEarlyFragmentTests;
|
||||
vk::SubpassDependency()
|
||||
.setSrcSubpass(VK_SUBPASS_EXTERNAL)
|
||||
.setDstSubpass(0)
|
||||
.setSrcStageMask(vk::PipelineStageFlagBits::eEarlyFragmentTests |
|
||||
vk::PipelineStageFlagBits::eLateFragmentTests)
|
||||
.setDstStageMask(vk::PipelineStageFlagBits::eEarlyFragmentTests |
|
||||
vk::PipelineStageFlagBits::eLateFragmentTests)
|
||||
.setSrcAccessMask({})
|
||||
.setDstAccessMask(vk::AccessFlagBits::eDepthStencilAttachmentWrite),
|
||||
};
|
||||
|
||||
const auto subpassSrcAccessMask = vk::AccessFlags() | vk::AccessFlagBits::eDepthStencilAttachmentWrite;
|
||||
|
||||
const auto subpassDstAccessMask = vk::AccessFlags() | vk::AccessFlagBits::eColorAttachmentWrite |
|
||||
vk::AccessFlagBits::eDepthStencilAttachmentWrite;
|
||||
|
||||
const auto subpassDependency = vk::SubpassDependency()
|
||||
.setSrcSubpass(VK_SUBPASS_EXTERNAL)
|
||||
.setDstSubpass(0)
|
||||
.setSrcStageMask(subpassSrcStageMask)
|
||||
.setDstStageMask(subpassDstStageMask)
|
||||
.setSrcAccessMask(subpassSrcAccessMask)
|
||||
.setDstAccessMask(subpassDstAccessMask);
|
||||
|
||||
const std::array<vk::AttachmentDescription, 2> attachments = {colorAttachment, depthAttachment};
|
||||
const auto renderPassCreateInfo =
|
||||
vk::RenderPassCreateInfo().setAttachments(attachments).setSubpasses(subpass).setDependencies(subpassDependency);
|
||||
vk::RenderPassCreateInfo().setAttachments(attachments).setSubpasses(subpass).setDependencies(dependencies);
|
||||
|
||||
renderPass = device->createRenderPassUnique(renderPassCreateInfo);
|
||||
|
||||
|
||||
@@ -60,7 +60,13 @@ VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE
|
||||
#endif
|
||||
|
||||
#include "renderdoc_app.h"
|
||||
static RENDERDOC_API_1_1_2* g_rdoc_api = nullptr;
|
||||
|
||||
static struct {
|
||||
RENDERDOC_API_1_1_2* api = nullptr;
|
||||
bool loop = false;
|
||||
int32_t frameDelay = 0;
|
||||
uint32_t frameCaptureCount = 0;
|
||||
} g_rdoc;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -187,13 +193,13 @@ void RendererBackend::initFrameCapture() {
|
||||
#ifdef _WIN32
|
||||
if (HMODULE mod = GetModuleHandleA("renderdoc.dll")) {
|
||||
pRENDERDOC_GetAPI RENDERDOC_GetAPI = (pRENDERDOC_GetAPI)GetProcAddress(mod, "RENDERDOC_GetAPI");
|
||||
int ret = RENDERDOC_GetAPI(eRENDERDOC_API_Version_1_1_2, (void**)&g_rdoc_api);
|
||||
int ret = RENDERDOC_GetAPI(eRENDERDOC_API_Version_1_1_2, (void**)&g_rdoc.api);
|
||||
assert(ret == 1);
|
||||
}
|
||||
#elif __unix__
|
||||
if (void* mod = dlopen("librenderdoc.so", RTLD_NOW | RTLD_NOLOAD)) {
|
||||
pRENDERDOC_GetAPI RENDERDOC_GetAPI = (pRENDERDOC_GetAPI)dlsym(mod, "RENDERDOC_GetAPI");
|
||||
int ret = RENDERDOC_GetAPI(eRENDERDOC_API_Version_1_1_2, (void**)&g_rdoc_api);
|
||||
int ret = RENDERDOC_GetAPI(eRENDERDOC_API_Version_1_1_2, (void**)&g_rdoc.api);
|
||||
assert(ret == 1);
|
||||
}
|
||||
#endif
|
||||
@@ -203,22 +209,49 @@ void RendererBackend::initFrameCapture() {
|
||||
|
||||
void RendererBackend::startFrameCapture() {
|
||||
#ifdef ENABLE_RENDERDOC_FRAME_CAPTURE
|
||||
if (g_rdoc_api) {
|
||||
if (!g_rdoc.api) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (g_rdoc.loop) {
|
||||
RENDERDOC_DevicePointer devicePtr = RENDERDOC_DEVICEPOINTER_FROM_VKINSTANCE(instance->operator VkInstance_T*());
|
||||
g_rdoc_api->StartFrameCapture(devicePtr, nullptr);
|
||||
g_rdoc.api->StartFrameCapture(devicePtr, nullptr);
|
||||
} else {
|
||||
if (g_rdoc.frameCaptureCount > 0 && g_rdoc.frameDelay == 0) {
|
||||
g_rdoc.api->TriggerMultiFrameCapture(g_rdoc.frameCaptureCount);
|
||||
}
|
||||
|
||||
--g_rdoc.frameDelay;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void RendererBackend::endFrameCapture() {
|
||||
#ifdef ENABLE_RENDERDOC_FRAME_CAPTURE
|
||||
if (g_rdoc_api) {
|
||||
if (g_rdoc.api && g_rdoc.loop) {
|
||||
RENDERDOC_DevicePointer devicePtr = RENDERDOC_DEVICEPOINTER_FROM_VKINSTANCE(instance->operator VkInstance_T*());
|
||||
g_rdoc_api->EndFrameCapture(devicePtr, nullptr);
|
||||
g_rdoc.api->EndFrameCapture(devicePtr, nullptr);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void RendererBackend::setFrameCaptureLoop([[maybe_unused]] bool value) {
|
||||
#ifdef ENABLE_RENDERDOC_FRAME_CAPTURE
|
||||
g_rdoc.loop = value;
|
||||
#endif
|
||||
}
|
||||
|
||||
void RendererBackend::triggerFrameCapture([[maybe_unused]] uint32_t frameCount, [[maybe_unused]] uint32_t frameDelay) {
|
||||
#ifdef ENABLE_RENDERDOC_FRAME_CAPTURE
|
||||
if (!g_rdoc.api) {
|
||||
return;
|
||||
}
|
||||
|
||||
g_rdoc.frameCaptureCount = frameCount;
|
||||
g_rdoc.frameDelay = frameDelay;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef ENABLE_VULKAN_VALIDATION
|
||||
|
||||
static VKAPI_ATTR VkBool32 VKAPI_CALL vkDebugUtilsCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
|
||||
|
||||
@@ -74,6 +74,22 @@ void UniformBufferArray::bindDescriptorSets(CommandEncoder& encoder) {
|
||||
}
|
||||
|
||||
descriptorSet->update(*this, descriptorStartIndex, descriptorStorageCount, descriptorUniformCount);
|
||||
|
||||
const auto frameCount = encoder.getContext().getBackend().getMaxFrames();
|
||||
const int32_t currentIndex = encoder.getContext().getCurrentFrameResourceIndex();
|
||||
const int32_t prevIndex = currentIndex == 0 ? frameCount - 1 : currentIndex - 1;
|
||||
|
||||
for (uint32_t i = 0; i < descriptorStorageCount + descriptorUniformCount; ++i) {
|
||||
const uint32_t index = descriptorStartIndex + i;
|
||||
|
||||
if (!uniformBufferVector[index]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto& buff = static_cast<UniformBuffer*>(uniformBufferVector[index].get())->mutableBufferResource();
|
||||
buff.updateVulkanBuffer(currentIndex, prevIndex);
|
||||
}
|
||||
|
||||
descriptorSet->bind(encoder);
|
||||
}
|
||||
|
||||
|
||||
@@ -85,7 +85,7 @@ static const std::unique_ptr<gfx::VertexBufferResource> noBuffer;
|
||||
|
||||
const gfx::UniqueVertexBufferResource& UploadPass::getBuffer(const gfx::VertexVectorBasePtr& vec,
|
||||
const gfx::BufferUsageType usage,
|
||||
bool forceUpdate) {
|
||||
[[maybe_unused]] bool forceUpdate) {
|
||||
if (vec) {
|
||||
const auto* rawBufPtr = vec->getRawData();
|
||||
const auto rawBufSize = vec->getRawCount() * vec->getRawSize();
|
||||
@@ -96,11 +96,11 @@ const gfx::UniqueVertexBufferResource& UploadPass::getBuffer(const gfx::VertexVe
|
||||
|
||||
// If it's changed, update it
|
||||
if (rawBufSize <= resource.getSizeInBytes()) {
|
||||
if (forceUpdate || vec->isModifiedAfter(resource.getLastUpdated())) {
|
||||
updateVertexBufferResource(resource, rawBufPtr, rawBufSize);
|
||||
resource.setLastUpdated(vec->getLastModified());
|
||||
if (vec->isModifiedAfter(resource.getLastUpdated())) {
|
||||
// updateVertexBufferResource(resource, rawBufPtr, rawBufSize);
|
||||
} else {
|
||||
return rawData->resource;
|
||||
}
|
||||
return rawData->resource;
|
||||
}
|
||||
}
|
||||
// Otherwise, create a new one
|
||||
@@ -108,6 +108,10 @@ const gfx::UniqueVertexBufferResource& UploadPass::getBuffer(const gfx::VertexVe
|
||||
auto buffer = std::make_unique<VertexBuffer>();
|
||||
buffer->resource = createVertexBufferResource(rawBufPtr, rawBufSize, usage, /*persistent=*/false);
|
||||
vec->setBuffer(std::move(buffer));
|
||||
|
||||
auto* rawData = static_cast<VertexBuffer*>(vec->getBuffer());
|
||||
auto& resource = static_cast<VertexBufferResource&>(*rawData->resource);
|
||||
resource.setLastUpdated(vec->getLastModified());
|
||||
return static_cast<VertexBuffer*>(vec->getBuffer())->resource;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user