Skip to content

Commit

Permalink
vulkan: VulkanContext/Platform refactor (#6810)
Browse files Browse the repository at this point in the history
We need to keep the context handles as part of the platform
class so that we can implement the new swapchain API based
on them.

 - Move creation of "context" handles from Context to Platform
 - VulkanContext contains immutable data
 - Change constructor of classes that depended on VulkanContext
 - Move timer query logic from VulkanDriver to VulkanTimerQuery
   and VulkanTimestamps
  • Loading branch information
poweifeng committed May 18, 2023
1 parent a71baef commit ddfeaef
Show file tree
Hide file tree
Showing 31 changed files with 1,411 additions and 1,299 deletions.
4 changes: 2 additions & 2 deletions filament/backend/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -197,9 +197,9 @@ if (FILAMENT_SUPPORTS_VULKAN)
src/vulkan/VulkanUtility.h
)
if (ANDROID OR LINUX OR WIN32)
list(APPEND SRCS src/vulkan/platform/PlatformVulkanAndroidLinuxWindows.cpp)
list(APPEND SRCS src/vulkan/platform/VulkanPlatformAndroidLinuxWindows.cpp)
elseif (APPLE OR IOS)
list(APPEND SRCS src/vulkan/platform/PlatformVulkanApple.mm)
list(APPEND SRCS src/vulkan/platform/VulkanPlatformApple.mm)
endif()
endif()

Expand Down
79 changes: 75 additions & 4 deletions filament/backend/include/backend/platforms/VulkanPlatform.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@

#include <backend/Platform.h>

#include <bluevk/BlueVK.h>
#include <utils/FixedCapacityVector.h>

#include <unordered_set>

namespace filament::backend {

/**
Expand All @@ -27,14 +32,80 @@ namespace filament::backend {

class VulkanPlatform : public Platform {
public:
~VulkanPlatform() override;

Driver* createDriver(void* const sharedContext,
Platform::DriverConfig const& driverConfig) noexcept override;
Platform::DriverConfig const& driverConfig) noexcept override;

int getOSVersion() const noexcept override { return 0; }

~VulkanPlatform() override;

/**
* Clean up any resources owned by the Platform. For example, if the Vulkan instance handle was
* generated by the platform, we need to clean it up in this method.
*/
virtual void terminate();

/**
* @return The instance (VkInstance) for the Vulkan backend.
*/
inline VkInstance getInstance() const noexcept { return mInstance; }

/**
* @return The logical device (VkDevice) that was selected as the backend device.
*/
inline VkDevice getDevice() const noexcept { return mDevice; }

/**
* @return The physical device (i.e gpu) that was selected as the backend physical device.
*/
inline VkPhysicalDevice getPhysicalDevice() const noexcept { return mPhysicalDevice; }

/**
* @return The family index of the graphics queue selected for the Vulkan backend.
*/
inline uint32_t getGraphicsQueueFamilyIndex() const noexcept {
return mGraphicsQueueFamilyIndex;
}

/**
* @return The index of the graphics queue (if there are multiple graphics queues)
* selected for the Vulkan backend.
*/
inline uint32_t getGraphicsQueueIndex() const noexcept { return mGraphicsQueueIndex; }

/**
* @return The queue that was selected for the Vulkan backend.
*/
inline VkQueue getGraphicsQueue() const noexcept { return mGraphicsQueue; }

// TODO: move this to private when swapchains are created via platform.
struct SurfaceBundle {
void* surface;
// On certain platforms, the extent of the surface cannot be queried from Vulkan. In those
// situations, we allow the frontend to pass in the extent to use in creating the swap
// chains. Platform implementation should set extent to 0 if they do not expect to set the
// swap chain extent.
uint32_t width;
uint32_t height;
};
static SurfaceBundle createVkSurfaceKHR(void* nativeWindow, VkInstance instance,
uint64_t flags) noexcept;

private:
using ExtensionSet = std::unordered_set<std::string_view>;
static ExtensionSet getRequiredInstanceExtensions();

protected:
VkInstance mInstance = VK_NULL_HANDLE;
VkPhysicalDevice mPhysicalDevice = VK_NULL_HANDLE;
VkDevice mDevice = VK_NULL_HANDLE;
uint32_t mGraphicsQueueFamilyIndex = 0xFFFFFFFF;
uint32_t mGraphicsQueueIndex = 0;

VkQueue mGraphicsQueue = VK_NULL_HANDLE;
};

} // namespace filament::backend
}// namespace filament::backend

#endif //TNT_FILAMENT_BACKEND_PLATFORMS_VULKANPLATFORM_H
#endif//TNT_FILAMENT_BACKEND_PLATFORMS_VULKANPLATFORM_H
4 changes: 2 additions & 2 deletions filament/backend/src/PlatformFactory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
#endif

#if defined(FILAMENT_DRIVER_SUPPORTS_VULKAN)
#include "vulkan/platform/PlatformVulkan.h"
#include "backend/platforms/VulkanPlatform.h"
#endif

#if defined (FILAMENT_SUPPORTS_METAL)
Expand Down Expand Up @@ -97,7 +97,7 @@ Platform* PlatformFactory::create(Backend* backend) noexcept {
}
if (*backend == Backend::VULKAN) {
#if defined(FILAMENT_DRIVER_SUPPORTS_VULKAN)
return new PlatformVulkan();
return new VulkanPlatform();
#else
return nullptr;
#endif
Expand Down
60 changes: 38 additions & 22 deletions filament/backend/src/vulkan/VulkanBlitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,13 +110,28 @@ struct BlitterUniforms {

}// anonymous namespace

VulkanBlitter::VulkanBlitter(VulkanStagePool& stagePool, VulkanPipelineCache& pipelineCache,
VulkanFboCache& fboCache, VulkanSamplerCache& samplerCache) noexcept
: mStagePool(stagePool), mPipelineCache(pipelineCache), mFramebufferCache(fboCache),
mSamplerCache(samplerCache) {}

void VulkanBlitter::initialize(VkPhysicalDevice physicalDevice, VkDevice device,
VmaAllocator allocator, std::shared_ptr<VulkanCommands> commands,
std::shared_ptr<VulkanTexture> emptyTexture) noexcept {
mPhysicalDevice = physicalDevice;
mDevice = device;
mAllocator = allocator;
mCommands = commands;
mEmptyTexture = emptyTexture;
}

void VulkanBlitter::blitColor(BlitArgs args) {
const VulkanAttachment src = args.srcTarget->getColor(args.targetIndex);
const VulkanAttachment dst = args.dstTarget->getColor(0);
const VkImageAspectFlags aspect = VK_IMAGE_ASPECT_COLOR_BIT;

#if FILAMENT_VULKAN_CHECK_BLIT_FORMAT
const VkPhysicalDevice gpu = mContext.physicalDevice;
VkPhysicalDevice const gpu = mPhysicalDevice;
VkFormatProperties info;
vkGetPhysicalDeviceFormatProperties(gpu, src.getFormat(), &info);
if (!ASSERT_POSTCONDITION_NON_FATAL(info.optimalTilingFeatures & VK_FORMAT_FEATURE_BLIT_SRC_BIT,
Expand All @@ -129,7 +144,7 @@ void VulkanBlitter::blitColor(BlitArgs args) {
return;
}
#endif
VkCommandBuffer const cmdbuffer = mContext.commands->get().cmdbuffer;
VkCommandBuffer const cmdbuffer = mCommands->get().cmdbuffer;
blitFast(cmdbuffer, aspect, args.filter, args.srcTarget->getExtent(), src, dst,
args.srcRectPair, args.dstRectPair);
}
Expand All @@ -140,7 +155,7 @@ void VulkanBlitter::blitDepth(BlitArgs args) {
const VkImageAspectFlags aspect = VK_IMAGE_ASPECT_DEPTH_BIT;

#if FILAMENT_VULKAN_CHECK_BLIT_FORMAT
const VkPhysicalDevice gpu = mContext.physicalDevice;
VkPhysicalDevice const gpu = mPhysicalDevice;
VkFormatProperties info;
vkGetPhysicalDeviceFormatProperties(gpu, src.getFormat(), &info);
if (!ASSERT_POSTCONDITION_NON_FATAL(info.optimalTilingFeatures & VK_FORMAT_FEATURE_BLIT_SRC_BIT,
Expand All @@ -161,29 +176,31 @@ void VulkanBlitter::blitDepth(BlitArgs args) {
args.dstRectPair);
return;
}
VkCommandBuffer const cmdbuffer = mContext.commands->get().cmdbuffer;
VkCommandBuffer const cmdbuffer = mCommands->get().cmdbuffer;
blitFast(cmdbuffer, aspect, args.filter, args.srcTarget->getExtent(), src, dst, args.srcRectPair,
args.dstRectPair);
}


void VulkanBlitter::shutdown() noexcept {
if (mContext.device) {
if (mDevice) {
delete mDepthResolveProgram;
mDepthResolveProgram = nullptr;

if (mTriangleBuffer) {
mTriangleBuffer->terminate(mContext);
mTriangleBuffer->terminate();
delete mTriangleBuffer;
mTriangleBuffer = nullptr;
}

if (mParamsBuffer) {
mParamsBuffer->terminate(mContext);
mParamsBuffer->terminate();
delete mParamsBuffer;
mParamsBuffer = nullptr;
}
}

mCommands.reset();
mEmptyTexture.reset();
}

// If we created these shader modules in the constructor, the device might not be ready yet.
Expand All @@ -192,9 +209,9 @@ void VulkanBlitter::lazyInit() noexcept {
if (mDepthResolveProgram != nullptr) {
return;
}
assert_invariant(mContext.device);
assert_invariant(mDevice);

auto decode = [device = mContext.device](const uint8_t* compressed, int compressedSize) {
auto decode = [device = mDevice](const uint8_t* compressed, int compressedSize) {
const size_t spirvSize = smolv::GetDecodedBufferSize(compressed, compressedSize);
FixedCapacityVector<uint8_t> spirv(spirvSize);
smolv::Decode(compressed, compressedSize, spirv.data(), spirvSize);
Expand All @@ -213,7 +230,7 @@ void VulkanBlitter::lazyInit() noexcept {

VkShaderModule vertexShader = decode(VKSHADERS_BLITDEPTHVS_DATA, VKSHADERS_BLITDEPTHVS_SIZE);
VkShaderModule fragmentShader = decode(VKSHADERS_BLITDEPTHFS_DATA, VKSHADERS_BLITDEPTHFS_SIZE);
mDepthResolveProgram = new VulkanProgram(mContext, vertexShader, fragmentShader);
mDepthResolveProgram = new VulkanProgram(mDevice, vertexShader, fragmentShader);

// Allocate one anonymous sampler at slot 0.
mDepthResolveProgram->samplerGroupInfo[0].samplers.reserve(1);
Expand All @@ -232,14 +249,13 @@ void VulkanBlitter::lazyInit() noexcept {
+1.0f, +1.0f,
};

mTriangleBuffer = new VulkanBuffer(mContext, mStagePool, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
sizeof(kTriangleVertices));
mTriangleBuffer = new VulkanBuffer(mAllocator, mCommands, mStagePool,
VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, sizeof(kTriangleVertices));

mTriangleBuffer->loadFromCpu(mContext, mStagePool,
kTriangleVertices, 0, sizeof(kTriangleVertices));
mTriangleBuffer->loadFromCpu(kTriangleVertices, 0, sizeof(kTriangleVertices));

mParamsBuffer = new VulkanBuffer(mContext, mStagePool, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
sizeof(BlitterUniforms));
mParamsBuffer = new VulkanBuffer(mAllocator, mCommands, mStagePool,
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, sizeof(BlitterUniforms));
}

// At a high level, the procedure for resolving depth looks like this:
Expand All @@ -256,7 +272,7 @@ void VulkanBlitter::blitSlowDepth(VkImageAspectFlags aspect, VkFilter filter,
.sampleCount = src.texture->samples,
.inverseSampleCount = 1.0f / float(src.texture->samples),
};
mParamsBuffer->loadFromCpu(mContext, mStagePool, &uniforms, 0, sizeof(uniforms));
mParamsBuffer->loadFromCpu(&uniforms, 0, sizeof(uniforms));

// BEGIN RENDER PASS
// -----------------
Expand Down Expand Up @@ -304,10 +320,10 @@ void VulkanBlitter::blitSlowDepth(VkImageAspectFlags aspect, VkFilter filter,
renderPassInfo.clearValueCount = 1;
renderPassInfo.pClearValues = clearValues;

const VkCommandBuffer cmdbuffer = mContext.commands->get().cmdbuffer;
const VkCommandBuffer cmdbuffer = mCommands->get().cmdbuffer;
vkCmdBeginRenderPass(cmdbuffer, &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);

VkViewport viewport = mContext.viewport = {
VkViewport viewport = {
.x = (float) dstRect[0].x,
.y = (float) dstRect[0].y,
.width = (float) renderPassInfo.renderArea.extent.width,
Expand All @@ -324,7 +340,7 @@ void VulkanBlitter::blitSlowDepth(VkImageAspectFlags aspect, VkFilter filter,
mPipelineCache.bindProgram(*mDepthResolveProgram);
mPipelineCache.bindPrimitiveTopology(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP);

auto& vkraster = mContext.rasterState;
auto vkraster = mPipelineCache.getCurrentRasterState();
vkraster.depthWriteEnable = true;
vkraster.depthCompareOp = SamplerCompareFunc::A;
vkraster.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT,
Expand Down Expand Up @@ -358,7 +374,7 @@ void VulkanBlitter::blitSlowDepth(VkImageAspectFlags aspect, VkFilter filter,
for (auto& sampler : samplers) {
sampler = {
.sampler = vksampler,
.imageView = mContext.emptyTexture->getPrimaryImageView(),
.imageView = mEmptyTexture->getPrimaryImageView(),
.imageLayout = ImgUtil::getVkLayout(VulkanLayout::READ_WRITE),
};
}
Expand Down
26 changes: 17 additions & 9 deletions filament/backend/src/vulkan/VulkanBlitter.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@

#include "VulkanContext.h"

#include <utils/compiler.h>

namespace filament::backend {

class VulkanBuffer;
Expand All @@ -30,11 +32,12 @@ struct VulkanProgram;

class VulkanBlitter {
public:
VulkanBlitter(VulkanContext& context, VulkanStagePool& stagePool,
VulkanPipelineCache& pipelineCache, VulkanFboCache& fboCache,
VulkanSamplerCache& samplerCache) :
mContext(context), mStagePool(stagePool), mPipelineCache(pipelineCache),
mFramebufferCache(fboCache), mSamplerCache(samplerCache) {}
VulkanBlitter(VulkanStagePool& stagePool, VulkanPipelineCache& pipelineCache,
VulkanFboCache& fboCache, VulkanSamplerCache& samplerCache) noexcept;

void initialize(VkPhysicalDevice physicalDevice, VkDevice device, VmaAllocator allocator,
std::shared_ptr<VulkanCommands> commands,
std::shared_ptr<VulkanTexture> emptyTexture) noexcept;

struct BlitArgs {
const VulkanRenderTarget* dstTarget;
Expand All @@ -53,15 +56,20 @@ class VulkanBlitter {
private:
void lazyInit() noexcept;

void blitSlowDepth(VkImageAspectFlags aspect, VkFilter filter,
const VkExtent2D srcExtent, VulkanAttachment src, VulkanAttachment dst,
const VkOffset3D srcRect[2], const VkOffset3D dstRect[2]);
void blitSlowDepth(VkImageAspectFlags aspect, VkFilter filter, const VkExtent2D srcExtent,
VulkanAttachment src, VulkanAttachment dst, const VkOffset3D srcRect[2],
const VkOffset3D dstRect[2]);

VulkanBuffer* mTriangleBuffer = nullptr;
VulkanBuffer* mParamsBuffer = nullptr;
VulkanProgram* mDepthResolveProgram = nullptr;

VulkanContext& mContext;
UTILS_UNUSED VkPhysicalDevice mPhysicalDevice;
VkDevice mDevice;
VmaAllocator mAllocator;
std::shared_ptr<VulkanCommands> mCommands;
std::shared_ptr<VulkanTexture> mEmptyTexture;

VulkanStagePool& mStagePool;
VulkanPipelineCache& mPipelineCache;
VulkanFboCache& mFramebufferCache;
Expand Down
24 changes: 12 additions & 12 deletions filament/backend/src/vulkan/VulkanBuffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,9 @@ using namespace bluevk;

namespace filament::backend {

VulkanBuffer::VulkanBuffer(VulkanContext& context, VulkanStagePool& stagePool,
VkBufferUsageFlags usage, uint32_t numBytes) : mUsage(usage) {
VulkanBuffer::VulkanBuffer(VmaAllocator allocator, std::shared_ptr<VulkanCommands> commands,
VulkanStagePool& stagePool, VkBufferUsageFlags usage, uint32_t numBytes)
: mAllocator(allocator), mCommands(commands), mStagePool(stagePool), mUsage(usage) {

// for now make sure that only 1 bit is set in usage
// (because loadFromCpu() assumes that somewhat)
Expand All @@ -38,31 +39,30 @@ VulkanBuffer::VulkanBuffer(VulkanContext& context, VulkanStagePool& stagePool,
};

VmaAllocationCreateInfo allocInfo { .usage = VMA_MEMORY_USAGE_GPU_ONLY };
vmaCreateBuffer(context.allocator, &bufferInfo, &allocInfo, &mGpuBuffer, &mGpuMemory, nullptr);
vmaCreateBuffer(mAllocator, &bufferInfo, &allocInfo, &mGpuBuffer, &mGpuMemory, nullptr);
}

VulkanBuffer::~VulkanBuffer() {
assert_invariant(mGpuMemory == VK_NULL_HANDLE);
assert_invariant(mGpuBuffer == VK_NULL_HANDLE);
}

void VulkanBuffer::terminate(VulkanContext& context) {
vmaDestroyBuffer(context.allocator, mGpuBuffer, mGpuMemory);
void VulkanBuffer::terminate() {
vmaDestroyBuffer(mAllocator, mGpuBuffer, mGpuMemory);
mGpuMemory = VK_NULL_HANDLE;
mGpuBuffer = VK_NULL_HANDLE;
}

void VulkanBuffer::loadFromCpu(VulkanContext& context, VulkanStagePool& stagePool,
const void* cpuData, uint32_t byteOffset, uint32_t numBytes) const {
void VulkanBuffer::loadFromCpu(const void* cpuData, uint32_t byteOffset, uint32_t numBytes) const {
assert_invariant(byteOffset == 0);
VulkanStage const* stage = stagePool.acquireStage(numBytes);
VulkanStage const* stage = mStagePool.acquireStage(numBytes);
void* mapped;
vmaMapMemory(context.allocator, stage->memory, &mapped);
vmaMapMemory(mAllocator, stage->memory, &mapped);
memcpy(mapped, cpuData, numBytes);
vmaUnmapMemory(context.allocator, stage->memory);
vmaFlushAllocation(context.allocator, stage->memory, byteOffset, numBytes);
vmaUnmapMemory(mAllocator, stage->memory);
vmaFlushAllocation(mAllocator, stage->memory, byteOffset, numBytes);

const VkCommandBuffer cmdbuffer = context.commands->get().cmdbuffer;
const VkCommandBuffer cmdbuffer = mCommands->get().cmdbuffer;

VkBufferCopy region{ .size = numBytes };
vkCmdCopyBuffer(cmdbuffer, stage->buffer, mGpuBuffer, 1, &region);
Expand Down
Loading

0 comments on commit ddfeaef

Please sign in to comment.