Skip to content

Commit

Permalink
vk: Implement protected content
Browse files Browse the repository at this point in the history
- Cache the render buffer in the render pass strucutre
- Enable the proteded path in the Render Target
- Make sure we build the protected version of the depth/color in the swap chaing
- Minor cleanup/restrucuring of the code
  • Loading branch information
phoenixxxx authored Nov 12, 2024
1 parent 96443fa commit 0108d66
Show file tree
Hide file tree
Showing 7 changed files with 68 additions and 44 deletions.
9 changes: 5 additions & 4 deletions filament/backend/src/vulkan/VulkanBlitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +126,7 @@ struct BlitterUniforms {
}// anonymous namespace

VulkanBlitter::VulkanBlitter(VkPhysicalDevice physicalDevice, VulkanCommands* commands) noexcept
: mPhysicalDevice(physicalDevice),
mCommands(commands) {}
: mPhysicalDevice(physicalDevice), mCommands(commands) {}

void VulkanBlitter::resolve(VulkanAttachment dst, VulkanAttachment src) {

Expand All @@ -151,7 +150,8 @@ void VulkanBlitter::resolve(VulkanAttachment dst, VulkanAttachment src) {
}
#endif

VulkanCommandBuffer& commands = mCommands->get();
VulkanCommandBuffer& commands = dst.texture->getIsProtected() ?
mCommands->getProtected() : mCommands->get();
commands.acquire(src.texture);
commands.acquire(dst.texture);
resolveFast(&commands, aspect, src, dst);
Expand All @@ -176,7 +176,8 @@ void VulkanBlitter::blit(VkFilter filter,
#endif
// src and dst should have the same aspect here
VkImageAspectFlags const aspect = src.texture->getImageAspect();
VulkanCommandBuffer& commands = mCommands->get();
VulkanCommandBuffer& commands = dst.texture->getIsProtected() ?
mCommands->getProtected() : mCommands->get();
commands.acquire(src.texture);
commands.acquire(dst.texture);
blitFast(&commands, aspect, filter, src, dst, srcRectPair, dstRectPair);
Expand Down
2 changes: 2 additions & 0 deletions filament/backend/src/vulkan/VulkanContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ class VulkanTimestamps {
};

struct VulkanRenderPass {
// Between the begin and end command render pass we cache the command buffer
VulkanCommandBuffer* commandBuffer;
VulkanRenderTarget* renderTarget;
VkRenderPass renderPass;
RenderPassParams params;
Expand Down
66 changes: 39 additions & 27 deletions filament/backend/src/vulkan/VulkanDriver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -201,8 +201,8 @@ VulkanDriver::VulkanDriver(VulkanPlatform* platform, VulkanContext const& contex
mResourceManager(&mResourceAllocator),
mThreadSafeResourceManager(&mResourceAllocator),
mCommands(mPlatform->getDevice(), mPlatform->getGraphicsQueue(),
mPlatform->getGraphicsQueueFamilyIndex(),
nullptr, 0, &mContext, &mResourceAllocator),
mPlatform->getGraphicsQueueFamilyIndex(), mPlatform->getProtectedGraphicsQueue(),
mPlatform->getProtectedGraphicsQueueFamilyIndex(), &mContext, &mResourceAllocator),
mPipelineLayoutCache(mPlatform->getDevice(), &mResourceAllocator),
mPipelineCache(mPlatform->getDevice(), mAllocator),
mStagePool(mAllocator, &mCommands),
Expand Down Expand Up @@ -682,7 +682,12 @@ void VulkanDriver::destroyRenderTarget(Handle<HwRenderTarget> rth) {
}

void VulkanDriver::createFenceR(Handle<HwFence> fh, int) {
VulkanCommandBuffer* cmdbuf = &mCommands.get();
VulkanCommandBuffer* cmdbuf;
if (mCurrentRenderPass.commandBuffer) {
cmdbuf = mCurrentRenderPass.commandBuffer;
} else {
cmdbuf = &mCommands.get();
}
mResourceAllocator.construct<VulkanFence>(fh, cmdbuf->getFenceStatus());
}

Expand All @@ -695,6 +700,13 @@ void VulkanDriver::createSwapChainR(Handle<HwSwapChain> sch, void* nativeWindow,
auto swapChain = mResourceAllocator.construct<VulkanSwapChain>(sch, mPlatform, mContext,
mAllocator, &mCommands, &mResourceAllocator, mStagePool, nativeWindow, flags);
mResourceManager.acquire(swapChain);

if (flags & backend::SWAP_CHAIN_CONFIG_PROTECTED_CONTENT) {
if (!isProtectedContentSupported()) {
utils::slog.w << "protected swapchain requested, but Vulkan does not support it"
<< utils::io::endl;
}
}
}

void VulkanDriver::createSwapChainHeadlessR(Handle<HwSwapChain> sch, uint32_t width,
Expand Down Expand Up @@ -1236,6 +1248,9 @@ void VulkanDriver::beginRenderPass(Handle<HwRenderTarget> rth, const RenderPassP
VkExtent2D const& extent = rt->getExtent();
assert_invariant(rt == mDefaultRenderTarget || extent.width > 0 && extent.height > 0);

VulkanCommandBuffer* commandBuffer = rt->isProtected() ?
&mCommands.getProtected() : &mCommands.get();

// Filament has the expectation that the contents of the swap chain are not preserved on the
// first render pass. Note however that its contents are often preserved on subsequent render
// passes, due to multiple views.
Expand All @@ -1260,8 +1275,7 @@ void VulkanDriver::beginRenderPass(Handle<HwRenderTarget> rth, const RenderPassP
// If that's the case, we need to change the layout of the texture to DEPTH_SAMPLER, which is a
// more general layout. Otherwise, we prefer the DEPTH_ATTACHMENT layout, which is optimal for
// the non-sampling case.
VulkanCommandBuffer& commands = mCommands.get();
VkCommandBuffer const cmdbuffer = commands.buffer();
VkCommandBuffer const cmdbuffer = commandBuffer->buffer();

// Scissor is reset with each render pass
// This also takes care of VUID-vkCmdDrawIndexed-None-07832.
Expand Down Expand Up @@ -1296,7 +1310,7 @@ void VulkanDriver::beginRenderPass(Handle<HwRenderTarget> rth, const RenderPassP
fbkey.renderPass = renderPass;
fbkey.layers = 1;

rt->emitBarriersBeginRenderPass(commands);
rt->emitBarriersBeginRenderPass(*commandBuffer);

VkFramebuffer vkfb = mFramebufferCache.getFramebuffer(fbkey);

Expand All @@ -1310,7 +1324,7 @@ void VulkanDriver::beginRenderPass(Handle<HwRenderTarget> rth, const RenderPassP
#endif

// The current command buffer now has references to the render target and its attachments.
commands.acquire(rt);
commandBuffer->acquire(rt);

// Populate the structures required for vkCmdBeginRenderPass.
VkRenderPassBeginInfo renderPassInfo {
Expand Down Expand Up @@ -1369,6 +1383,7 @@ void VulkanDriver::beginRenderPass(Handle<HwRenderTarget> rth, const RenderPassP
vkCmdSetViewport(cmdbuffer, 0, 1, &viewport);

mCurrentRenderPass = {
.commandBuffer = commandBuffer,
.renderTarget = rt,
.renderPass = renderPassInfo.renderPass,
.params = params,
Expand All @@ -1379,20 +1394,21 @@ void VulkanDriver::beginRenderPass(Handle<HwRenderTarget> rth, const RenderPassP
void VulkanDriver::endRenderPass(int) {
FVK_SYSTRACE_SCOPE();

VulkanCommandBuffer& commands = mCommands.get();
VkCommandBuffer cmdbuffer = commands.buffer();
VkCommandBuffer cmdbuffer = mCurrentRenderPass.commandBuffer->buffer();
vkCmdEndRenderPass(cmdbuffer);

VulkanRenderTarget* rt = mCurrentRenderPass.renderTarget;
assert_invariant(rt);

// Since we might soon be sampling from the render target that we just wrote to, we need a
// pipeline barrier between framebuffer writes and shader reads.
rt->emitBarriersEndRenderPass(commands);
rt->emitBarriersEndRenderPass(*mCurrentRenderPass.commandBuffer);

mRenderPassFboInfo = {};
mCurrentRenderPass.renderTarget = nullptr;
mCurrentRenderPass.renderPass = VK_NULL_HANDLE;

mCurrentRenderPass.commandBuffer = nullptr;
}

void VulkanDriver::nextSubpass(int) {
Expand All @@ -1403,7 +1419,8 @@ void VulkanDriver::nextSubpass(int) {
assert_invariant(renderTarget);
assert_invariant(mCurrentRenderPass.params.subpassMask);

vkCmdNextSubpass(mCommands.get().buffer(), VK_SUBPASS_CONTENTS_INLINE);
vkCmdNextSubpass(mCurrentRenderPass.commandBuffer->buffer(),
VK_SUBPASS_CONTENTS_INLINE);

mPipelineCache.bindRenderPass(mCurrentRenderPass.renderPass,
++mCurrentRenderPass.currentSubpass);
Expand Down Expand Up @@ -1446,9 +1463,8 @@ void VulkanDriver::commit(Handle<HwSwapChain> sch) {
void VulkanDriver::setPushConstant(backend::ShaderStage stage, uint8_t index,
backend::PushConstantVariant value) {
assert_invariant(mBoundPipeline.program && "Expect a program when writing to push constants");
VulkanCommands* commands = &mCommands;
mBoundPipeline.program->writePushConstant(commands, mBoundPipeline.pipelineLayout, stage, index,
value);
mBoundPipeline.program->writePushConstant(mCurrentRenderPass.commandBuffer,
mBoundPipeline.pipelineLayout, stage, index, value);
}

void VulkanDriver::insertEventMarker(char const* string) {
Expand Down Expand Up @@ -1628,7 +1644,6 @@ void VulkanDriver::blitDEPRECATED(TargetBufferFlags buffers,
void VulkanDriver::bindPipeline(PipelineState const& pipelineState) {
FVK_SYSTRACE_SCOPE();

VulkanCommandBuffer* commands = &mCommands.get();
const VulkanVertexBufferInfo& vbi =
*mResourceAllocator.handle_cast<VulkanVertexBufferInfo*>(pipelineState.vertexBufferInfo);

Expand All @@ -1637,7 +1652,7 @@ void VulkanDriver::bindPipeline(PipelineState const& pipelineState) {
PolygonOffset const& depthOffset = pipelineState.polygonOffset;

auto* program = mResourceAllocator.handle_cast<VulkanProgram*>(programHandle);
commands->acquire(program);
mCurrentRenderPass.commandBuffer->acquire(program);

// Update the VK raster state.
const VulkanRenderTarget* rt = mCurrentRenderPass.renderTarget;
Expand Down Expand Up @@ -1701,17 +1716,16 @@ void VulkanDriver::bindPipeline(PipelineState const& pipelineState) {
};

mPipelineCache.bindLayout(pipelineLayout);
mPipelineCache.bindPipeline(commands);
mPipelineCache.bindPipeline(mCurrentRenderPass.commandBuffer);
}

void VulkanDriver::bindRenderPrimitive(Handle<HwRenderPrimitive> rph) {
FVK_SYSTRACE_SCOPE();

VulkanCommandBuffer* commands = &mCommands.get();
VkCommandBuffer cmdbuffer = commands->buffer();
VkCommandBuffer cmdbuffer = mCurrentRenderPass.commandBuffer->buffer();
const VulkanRenderPrimitive& prim = *mResourceAllocator.handle_cast<VulkanRenderPrimitive*>(rph);
commands->acquire(prim.indexBuffer);
commands->acquire(prim.vertexBuffer);
mCurrentRenderPass.commandBuffer->acquire(prim.indexBuffer);
mCurrentRenderPass.commandBuffer->acquire(prim.vertexBuffer);

// This *must* match the VulkanVertexBufferInfo that was bound in bindPipeline(). But we want
// to allow to call this before bindPipeline(), so the validation can only happen in draw()
Expand Down Expand Up @@ -1744,11 +1758,10 @@ void VulkanDriver::bindDescriptorSet(

void VulkanDriver::draw2(uint32_t indexOffset, uint32_t indexCount, uint32_t instanceCount) {
FVK_SYSTRACE_SCOPE();
VkCommandBuffer cmdbuffer = mCurrentRenderPass.commandBuffer->buffer();

VulkanCommandBuffer& commands = mCommands.get();
VkCommandBuffer cmdbuffer = commands.buffer();

mDescriptorSetManager.commit(&commands, mBoundPipeline.pipelineLayout,
mDescriptorSetManager.commit(mCurrentRenderPass.commandBuffer,
mBoundPipeline.pipelineLayout,
mBoundPipeline.descriptorSetMask);

// Finally, make the actual draw call. TODO: support subranges
Expand All @@ -1774,8 +1787,7 @@ void VulkanDriver::dispatchCompute(Handle<HwProgram> program, math::uint3 workGr
}

void VulkanDriver::scissor(Viewport scissorBox) {
VulkanCommandBuffer& commands = mCommands.get();
VkCommandBuffer cmdbuffer = commands.buffer();
VkCommandBuffer cmdbuffer = mCurrentRenderPass.commandBuffer->buffer();

// TODO: it's a common case that scissor() is called with (0, 0, maxint, maxint)
// we should maybe have a fast path for this and avoid vkCmdSetScissor() if possible
Expand Down
6 changes: 4 additions & 2 deletions filament/backend/src/vulkan/VulkanHandles.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -164,9 +164,9 @@ PushConstantDescription::PushConstantDescription(backend::Program const& program
}
}

void PushConstantDescription::write(VulkanCommands* commands, VkPipelineLayout layout,
void PushConstantDescription::write(VulkanCommandBuffer* cmdbuf, VkPipelineLayout layout,
backend::ShaderStage stage, uint8_t index, backend::PushConstantVariant const& value) {
VulkanCommandBuffer* cmdbuf = &(commands->get());

uint32_t binaryValue = 0;
UTILS_UNUSED_IN_RELEASE auto const& types = mTypes[(uint8_t) stage];
if (std::holds_alternative<bool>(value)) {
Expand Down Expand Up @@ -340,6 +340,8 @@ VulkanRenderTarget::VulkanRenderTarget(VkDevice device, VkPhysicalDevice physica
continue;
}

mProtected |= texture->getIsProtected();

attachments.push_back(attachment);
mInfo->colors.set(index);

Expand Down
6 changes: 3 additions & 3 deletions filament/backend/src/vulkan/VulkanHandles.h
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ struct PushConstantDescription {

uint32_t getVkRangeCount() const noexcept { return mRangeCount; }

void write(VulkanCommands* commands, VkPipelineLayout layout, backend::ShaderStage stage,
void write(VulkanCommandBuffer* cmdbuf, VkPipelineLayout layout, backend::ShaderStage stage,
uint8_t index, backend::PushConstantVariant const& value);

private:
Expand Down Expand Up @@ -218,9 +218,9 @@ struct VulkanProgram : public HwProgram, VulkanResource {
return mInfo->pushConstantDescription.getVkRanges();
}

inline void writePushConstant(VulkanCommands* commands, VkPipelineLayout layout,
inline void writePushConstant(VulkanCommandBuffer* cmdbuf, VkPipelineLayout layout,
backend::ShaderStage stage, uint8_t index, backend::PushConstantVariant const& value) {
mInfo->pushConstantDescription.write(commands, layout, stage, index, value);
mInfo->pushConstantDescription.write(cmdbuf, layout, stage, index, value);
}

#if FVK_ENABLED_DEBUG_SAMPLER_NAME
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ namespace filament::backend {
namespace {

std::tuple<VkImage, VkDeviceMemory> createImageAndMemory(VulkanContext const& context,
VkDevice device, VkExtent2D extent, VkFormat format) {
VkDevice device, VkExtent2D extent, VkFormat format,
bool isProtected) {
bool const isDepth = isVkDepthFormat(format);
// Filament expects blit() to work with any texture, so we almost always set these usage flags
// (see copyFrame() and readPixels()).
Expand All @@ -38,6 +39,7 @@ std::tuple<VkImage, VkDeviceMemory> createImageAndMemory(VulkanContext const& co

VkImageCreateInfo imageInfo {
.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
.flags = isProtected ? VK_IMAGE_CREATE_PROTECTED_BIT : VkImageCreateFlags(0),
.imageType = VK_IMAGE_TYPE_2D,
.format = format,
.extent = {extent.width, extent.height, 1},
Expand All @@ -58,8 +60,11 @@ std::tuple<VkImage, VkDeviceMemory> createImageAndMemory(VulkanContext const& co
VkMemoryRequirements memReqs;
vkGetImageMemoryRequirements(device, image, &memReqs);

const VkFlags requiredMemoryFlags =
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
(isProtected ? VK_MEMORY_PROPERTY_PROTECTED_BIT : 0U);
uint32_t memoryTypeIndex
= context.selectMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
= context.selectMemoryType(memReqs.memoryTypeBits, requiredMemoryFlags);

FILAMENT_CHECK_POSTCONDITION(memoryTypeIndex < VK_MAX_MEMORY_TYPES)
<< "VulkanPlatformSwapChainImpl: unable to find a memory type that meets requirements.";
Expand Down Expand Up @@ -110,8 +115,9 @@ void VulkanPlatformSwapChainImpl::destroy() {
mSwapChainBundle.colors.clear();
}

VkImage VulkanPlatformSwapChainImpl::createImage(VkExtent2D extent, VkFormat format) {
auto [image, memory] = createImageAndMemory(mContext, mDevice, extent, format);
VkImage VulkanPlatformSwapChainImpl::createImage(VkExtent2D extent, VkFormat format,
bool isProtected) {
auto [image, memory] = createImageAndMemory(mContext, mDevice, extent, format, isProtected);
mMemory.insert({image, memory});
return image;
}
Expand Down Expand Up @@ -248,7 +254,8 @@ VkResult VulkanPlatformSurfaceSwapChain::create() {
mSwapChainBundle.colorFormat = surfaceFormat.format;
mSwapChainBundle.depthFormat =
selectDepthFormat(mContext.getAttachmentDepthStencilFormats(), mHasStencil);
mSwapChainBundle.depth = createImage(mSwapChainBundle.extent, mSwapChainBundle.depthFormat);
mSwapChainBundle.depth = createImage(mSwapChainBundle.extent,
mSwapChainBundle.depthFormat, mIsProtected);
mSwapChainBundle.isProtected = mIsProtected;

FVK_LOGI << "vkCreateSwapchain"
Expand Down Expand Up @@ -356,13 +363,13 @@ VulkanPlatformHeadlessSwapChain::VulkanPlatformHeadlessSwapChain(VulkanContext c
images.reserve(HEADLESS_SWAPCHAIN_SIZE);
images.resize(HEADLESS_SWAPCHAIN_SIZE);
for (size_t i = 0; i < HEADLESS_SWAPCHAIN_SIZE; ++i) {
images[i] = createImage(extent, mSwapChainBundle.colorFormat);
images[i] = createImage(extent, mSwapChainBundle.colorFormat, false);
}

bool const hasStencil = (flags & backend::SWAP_CHAIN_HAS_STENCIL_BUFFER) != 0;
mSwapChainBundle.depthFormat =
selectDepthFormat(mContext.getAttachmentDepthStencilFormats(), hasStencil);
mSwapChainBundle.depth = createImage(extent, mSwapChainBundle.depthFormat);
mSwapChainBundle.depth = createImage(extent, mSwapChainBundle.depthFormat, false);
}

VulkanPlatformHeadlessSwapChain::~VulkanPlatformHeadlessSwapChain() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ struct VulkanPlatformSwapChainImpl : public Platform::SwapChain {
// Non-virtual override-able method
void destroy();

VkImage createImage(VkExtent2D extent, VkFormat format);
VkImage createImage(VkExtent2D extent, VkFormat format, bool isProtected);

VulkanContext const& mContext;
VkDevice mDevice;
Expand Down

0 comments on commit 0108d66

Please sign in to comment.