Merge branch 'google:main' into main
This commit is contained in:
@@ -88,6 +88,7 @@ public:
|
||||
VkFormat colorFormat = VK_FORMAT_UNDEFINED;
|
||||
VkFormat depthFormat = VK_FORMAT_UNDEFINED;
|
||||
VkExtent2D extent = {0, 0};
|
||||
bool isProtected = false;
|
||||
};
|
||||
|
||||
struct ImageSyncData {
|
||||
@@ -199,6 +200,13 @@ public:
|
||||
*/
|
||||
virtual bool hasResized(SwapChainPtr handle);
|
||||
|
||||
/**
|
||||
* Check if the surface is protected.
|
||||
* @param handle The handle returned by createSwapChain()
|
||||
* @return Whether the swapchain is protected
|
||||
*/
|
||||
virtual bool isProtected(SwapChainPtr handle);
|
||||
|
||||
/**
|
||||
* Carry out a recreation of the swapchain.
|
||||
* @param handle The handle returned by createSwapChain()
|
||||
@@ -267,6 +275,23 @@ public:
|
||||
*/
|
||||
VkQueue getGraphicsQueue() const noexcept;
|
||||
|
||||
/**
|
||||
* @return The family index of the protected graphics queue selected for the
|
||||
* Vulkan backend.
|
||||
*/
|
||||
uint32_t getProtectedGraphicsQueueFamilyIndex() const noexcept;
|
||||
|
||||
/**
|
||||
* @return The index of the protected graphics queue (if there are multiple
|
||||
* graphics queues) selected for the Vulkan backend.
|
||||
*/
|
||||
uint32_t getProtectedGraphicsQueueIndex() const noexcept;
|
||||
|
||||
/**
|
||||
* @return The protected queue that was selected for the Vulkan backend.
|
||||
*/
|
||||
VkQueue getProtectedGraphicsQueue() const noexcept;
|
||||
|
||||
private:
|
||||
static ExtensionSet getSwapchainInstanceExtensions();
|
||||
|
||||
|
||||
@@ -1794,6 +1794,16 @@ void MetalDriver::bindDescriptorSet(
|
||||
backend::DescriptorSetHandle dsh,
|
||||
backend::descriptor_set_t set,
|
||||
backend::DescriptorSetOffsetArray&& offsets) {
|
||||
|
||||
if (UTILS_UNLIKELY(!dsh)) {
|
||||
DEBUG_LOG("bindDescriptorSet(dsh = null, set = %d, offsets = [])\n", set);
|
||||
mContext->currentDescriptorSets[set] = nullptr;
|
||||
mContext->vertexDescriptorBindings.setBuffer(nil, 0, set);
|
||||
mContext->fragmentDescriptorBindings.setBuffer(nil, 0, set);
|
||||
mContext->dynamicOffsets.setOffsets(set, nullptr, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
auto descriptorSet = handle_cast<MetalDescriptorSet>(dsh);
|
||||
const size_t dynamicBindings = descriptorSet->layout->getDynamicOffsetCount();
|
||||
utils::FixedCapacityVector<size_t> offsetsVector(dynamicBindings, 0);
|
||||
|
||||
@@ -3875,6 +3875,14 @@ void OpenGLDriver::bindDescriptorSet(
|
||||
backend::DescriptorSetHandle dsh,
|
||||
backend::descriptor_set_t set,
|
||||
backend::DescriptorSetOffsetArray&& offsets) {
|
||||
|
||||
if (UTILS_UNLIKELY(!dsh)) {
|
||||
mBoundDescriptorSets[set].dsh = dsh;
|
||||
mInvalidDescriptorSetBindings.set(set, true);
|
||||
mInvalidDescriptorSetBindingOffsets.set(set, true);
|
||||
return;
|
||||
}
|
||||
|
||||
// handle_cast<> here also serves to validate the handle (it actually cannot return nullptr)
|
||||
GLDescriptorSet const* const ds = handle_cast<GLDescriptorSet*>(dsh);
|
||||
if (ds) {
|
||||
|
||||
@@ -93,6 +93,9 @@ struct VulkanRenderPass {
|
||||
struct VulkanContext {
|
||||
public:
|
||||
inline uint32_t selectMemoryType(uint32_t flags, VkFlags reqs) const {
|
||||
if ((reqs & VK_MEMORY_PROPERTY_PROTECTED_BIT) != 0) {
|
||||
assert_invariant(isProtectedMemorySupported() == true);
|
||||
}
|
||||
for (uint32_t i = 0; i < VK_MAX_MEMORY_TYPES; i++) {
|
||||
if (flags & 1) {
|
||||
if ((mMemoryProperties.memoryTypes[i].propertyFlags & reqs) == reqs) {
|
||||
@@ -113,19 +116,19 @@ public:
|
||||
}
|
||||
|
||||
inline VkPhysicalDeviceLimits const& getPhysicalDeviceLimits() const noexcept {
|
||||
return mPhysicalDeviceProperties.limits;
|
||||
return mPhysicalDeviceProperties.properties.limits;
|
||||
}
|
||||
|
||||
inline uint32_t getPhysicalDeviceVendorId() const noexcept {
|
||||
return mPhysicalDeviceProperties.vendorID;
|
||||
return mPhysicalDeviceProperties.properties.vendorID;
|
||||
}
|
||||
|
||||
inline bool isImageCubeArraySupported() const noexcept {
|
||||
return mPhysicalDeviceFeatures.imageCubeArray == VK_TRUE;
|
||||
return mPhysicalDeviceFeatures.features.imageCubeArray == VK_TRUE;
|
||||
}
|
||||
|
||||
inline bool isDepthClampSupported() const noexcept {
|
||||
return mPhysicalDeviceFeatures.depthClamp == VK_TRUE;
|
||||
return mPhysicalDeviceFeatures.features.depthClamp == VK_TRUE;
|
||||
}
|
||||
|
||||
inline bool isDebugMarkersSupported() const noexcept {
|
||||
@@ -141,21 +144,30 @@ public:
|
||||
}
|
||||
|
||||
inline bool isClipDistanceSupported() const noexcept {
|
||||
return mPhysicalDeviceFeatures.shaderClipDistance == VK_TRUE;
|
||||
return mPhysicalDeviceFeatures.features.shaderClipDistance == VK_TRUE;
|
||||
}
|
||||
|
||||
inline bool isLazilyAllocatedMemorySupported() const noexcept {
|
||||
return mLazilyAllocatedMemorySupported;
|
||||
}
|
||||
|
||||
inline bool isProtectedMemorySupported() const noexcept {
|
||||
return mProtectedMemorySupported;
|
||||
}
|
||||
|
||||
private:
|
||||
VkPhysicalDeviceMemoryProperties mMemoryProperties = {};
|
||||
VkPhysicalDeviceProperties mPhysicalDeviceProperties = {};
|
||||
VkPhysicalDeviceFeatures mPhysicalDeviceFeatures = {};
|
||||
VkPhysicalDeviceProperties2 mPhysicalDeviceProperties = {
|
||||
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2
|
||||
};
|
||||
VkPhysicalDeviceFeatures2 mPhysicalDeviceFeatures = {
|
||||
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2
|
||||
};
|
||||
bool mDebugMarkersSupported = false;
|
||||
bool mDebugUtilsSupported = false;
|
||||
bool mMultiviewEnabled = false;
|
||||
bool mLazilyAllocatedMemorySupported = false;
|
||||
bool mProtectedMemorySupported = false;
|
||||
|
||||
VkFormatList mDepthStencilFormats;
|
||||
VkFormatList mBlittableDepthStencilFormats;
|
||||
|
||||
@@ -977,8 +977,7 @@ bool VulkanDriver::isSRGBSwapChainSupported() {
|
||||
}
|
||||
|
||||
bool VulkanDriver::isProtectedContentSupported() {
|
||||
// the SWAP_CHAIN_CONFIG_PROTECTED_CONTENT flag is not supported
|
||||
return false;
|
||||
return mContext.isProtectedMemorySupported();
|
||||
}
|
||||
|
||||
bool VulkanDriver::isStereoSupported() {
|
||||
@@ -1767,8 +1766,12 @@ void VulkanDriver::bindDescriptorSet(
|
||||
backend::DescriptorSetHandle dsh,
|
||||
backend::descriptor_set_t setIndex,
|
||||
backend::DescriptorSetOffsetArray&& offsets) {
|
||||
VulkanDescriptorSet* set = mResourceAllocator.handle_cast<VulkanDescriptorSet*>(dsh);
|
||||
mDescriptorSetManager.bind(setIndex, set, std::move(offsets));
|
||||
if (dsh) {
|
||||
VulkanDescriptorSet* set = mResourceAllocator.handle_cast<VulkanDescriptorSet*>(dsh);
|
||||
mDescriptorSetManager.bind(setIndex, set, std::move(offsets));
|
||||
} else {
|
||||
mDescriptorSetManager.unbind(setIndex);
|
||||
}
|
||||
}
|
||||
|
||||
void VulkanDriver::draw2(uint32_t indexOffset, uint32_t indexCount, uint32_t instanceCount) {
|
||||
|
||||
@@ -256,6 +256,7 @@ VulkanRenderTarget::VulkanRenderTarget()
|
||||
: HwRenderTarget(0, 0),
|
||||
VulkanResource(VulkanResourceType::RENDER_TARGET),
|
||||
mOffscreen(false),
|
||||
mProtected(false),
|
||||
mResources(nullptr),
|
||||
mInfo(std::make_unique<Auxiliary>()) {
|
||||
mInfo->rpkey.samples = mInfo->fbkey.samples = 1;
|
||||
@@ -267,6 +268,7 @@ void VulkanRenderTarget::bindToSwapChain(VulkanSwapChain& swapChain) {
|
||||
VkExtent2D const extent = swapChain.getExtent();
|
||||
width = extent.width;
|
||||
height = extent.height;
|
||||
mProtected = swapChain.isProtected();
|
||||
|
||||
VulkanAttachment color = {.texture = swapChain.getCurrentColor()};
|
||||
mInfo->attachments = {color};
|
||||
@@ -303,6 +305,7 @@ VulkanRenderTarget::VulkanRenderTarget(VkDevice device, VkPhysicalDevice physica
|
||||
: HwRenderTarget(width, height),
|
||||
VulkanResource(VulkanResourceType::RENDER_TARGET),
|
||||
mOffscreen(true),
|
||||
mProtected(false),
|
||||
mResources(handleAllocator),
|
||||
mInfo(std::make_unique<Auxiliary>()) {
|
||||
|
||||
|
||||
@@ -306,6 +306,7 @@ struct VulkanRenderTarget : private HwRenderTarget, VulkanResource {
|
||||
inline bool hasDepth() const { return mInfo->depthIndex != Auxiliary::UNDEFINED_INDEX; }
|
||||
|
||||
inline bool isSwapChain() const { return !mOffscreen; }
|
||||
inline bool isProtected() const { return mProtected; }
|
||||
|
||||
void bindToSwapChain(VulkanSwapChain& surf);
|
||||
|
||||
@@ -328,6 +329,7 @@ private:
|
||||
int8_t msaaIndex = UNDEFINED_INDEX;
|
||||
};
|
||||
bool const mOffscreen;
|
||||
bool mProtected;
|
||||
|
||||
VulkanAcquireOnlyResourceManager mResources;
|
||||
std::unique_ptr<Auxiliary> mInfo;
|
||||
|
||||
@@ -63,14 +63,20 @@ void VulkanSwapChain::update() {
|
||||
mColors.reserve(bundle.colors.size());
|
||||
VkDevice const device = mPlatform->getDevice();
|
||||
|
||||
TextureUsage depthUsage = TextureUsage::DEPTH_ATTACHMENT;
|
||||
TextureUsage colorUsage = TextureUsage::COLOR_ATTACHMENT;
|
||||
if (bundle.isProtected) {
|
||||
depthUsage |= TextureUsage::PROTECTED;
|
||||
colorUsage |= TextureUsage::PROTECTED;
|
||||
}
|
||||
for (auto const color: bundle.colors) {
|
||||
mColors.push_back(std::make_unique<VulkanTexture>(device, mAllocator, mCommands, mHandleAllocator,
|
||||
color, bundle.colorFormat, 1, bundle.extent.width, bundle.extent.height,
|
||||
TextureUsage::COLOR_ATTACHMENT, mStagePool, true /* heap allocated */));
|
||||
colorUsage, mStagePool, true /* heap allocated */));
|
||||
}
|
||||
mDepth = std::make_unique<VulkanTexture>(device, mAllocator, mCommands, mHandleAllocator,
|
||||
bundle.depth, bundle.depthFormat, 1, bundle.extent.width, bundle.extent.height,
|
||||
TextureUsage::DEPTH_ATTACHMENT, mStagePool, true /* heap allocated */);
|
||||
depthUsage, mStagePool, true /* heap allocated */);
|
||||
|
||||
mExtent = bundle.extent;
|
||||
}
|
||||
|
||||
@@ -74,6 +74,9 @@ struct VulkanSwapChain : public HwSwapChain, VulkanResource {
|
||||
return mExtent;
|
||||
}
|
||||
|
||||
inline bool isProtected() noexcept {
|
||||
return mPlatform->isProtected(swapChain);
|
||||
}
|
||||
private:
|
||||
static constexpr int IMAGE_READY_SEMAPHORE_COUNT = FVK_MAX_COMMAND_BUFFERS;
|
||||
|
||||
|
||||
@@ -147,12 +147,14 @@ inline VulkanLayout getDefaultLayoutImpl(VkImageUsageFlags vkusage) {
|
||||
|
||||
VulkanTextureState::VulkanTextureState(VkDevice device, VmaAllocator allocator,
|
||||
VulkanCommands* commands, VulkanStagePool& stagePool, VkFormat format,
|
||||
VkImageViewType viewType, uint8_t levels, uint8_t layerCount, VulkanLayout defaultLayout)
|
||||
VkImageViewType viewType, uint8_t levels, uint8_t layerCount, VulkanLayout defaultLayout,
|
||||
bool isProtected)
|
||||
: VulkanResource(VulkanResourceType::HEAP_ALLOCATED),
|
||||
mVkFormat(format),
|
||||
mViewType(viewType),
|
||||
mFullViewRange{filament::backend::getImageAspect(format), 0, levels, 0, layerCount},
|
||||
mDefaultLayout(defaultLayout),
|
||||
mIsProtected(isProtected),
|
||||
mStagePool(stagePool),
|
||||
mDevice(device),
|
||||
mAllocator(allocator),
|
||||
@@ -183,7 +185,8 @@ VulkanTexture::VulkanTexture(
|
||||
mState(handleAllocator->initHandle<VulkanTextureState>(
|
||||
device, allocator, commands, stagePool,
|
||||
format, imgutil::getViewType(SamplerType::SAMPLER_2D), 1, 1,
|
||||
getDefaultLayoutImpl(tusage))) {
|
||||
getDefaultLayoutImpl(tusage),
|
||||
any(usage& TextureUsage::PROTECTED))) {
|
||||
auto* const state = getSharedState();
|
||||
state->mTextureImage = image;
|
||||
mPrimaryViewRange = state->mFullViewRange;
|
||||
@@ -201,7 +204,7 @@ VulkanTexture::VulkanTexture(VkDevice device, VkPhysicalDevice physicalDevice,
|
||||
mAllocator(handleAllocator),
|
||||
mState(handleAllocator->initHandle<VulkanTextureState>(device, allocator, commands, stagePool,
|
||||
backend::getVkFormat(tformat), imgutil::getViewType(target), levels,
|
||||
getLayerCount(target, depth), VulkanLayout::UNDEFINED)) {
|
||||
getLayerCount(target, depth), VulkanLayout::UNDEFINED, any(usage& TextureUsage::PROTECTED))) {
|
||||
auto* const state = getSharedState();
|
||||
|
||||
// Create an appropriately-sized device-only VkImage, but do not fill it yet.
|
||||
@@ -232,6 +235,9 @@ VulkanTexture::VulkanTexture(VkDevice device, VkPhysicalDevice physicalDevice,
|
||||
imageInfo.arrayLayers = depth * 6;
|
||||
imageInfo.extent.depth = 1;
|
||||
}
|
||||
if (any(usage & TextureUsage::PROTECTED)) {
|
||||
imageInfo.flags |= VK_IMAGE_CREATE_PROTECTED_BIT;
|
||||
}
|
||||
|
||||
if (any(usage & TextureUsage::BLIT_SRC)) {
|
||||
imageInfo.usage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
|
||||
@@ -331,7 +337,8 @@ VulkanTexture::VulkanTexture(VkDevice device, VkPhysicalDevice physicalDevice,
|
||||
|
||||
const VkFlags requiredMemoryFlags =
|
||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
|
||||
(useTransientAttachment ? VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT : 0U);
|
||||
(useTransientAttachment ? VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT : 0U) |
|
||||
(state->mIsProtected ? VK_MEMORY_PROPERTY_PROTECTED_BIT : 0U);
|
||||
uint32_t memoryTypeIndex
|
||||
= context.selectMemoryType(memReqs.memoryTypeBits, requiredMemoryFlags);
|
||||
|
||||
@@ -416,6 +423,7 @@ void VulkanTexture::updateImage(const PixelBufferDescriptor& data, uint32_t widt
|
||||
assert_invariant(depth <= this->depth * ((target == SamplerType::SAMPLER_CUBEMAP ||
|
||||
target == SamplerType::SAMPLER_CUBEMAP_ARRAY) ? 6 : 1));
|
||||
auto* const state = getSharedState();
|
||||
assert_invariant(state->mIsProtected == false);
|
||||
const PixelBufferDescriptor* hostData = &data;
|
||||
PixelBufferDescriptor reshapedData;
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ class VulkanResourceAllocator;
|
||||
struct VulkanTextureState : public VulkanResource {
|
||||
VulkanTextureState(VkDevice device, VmaAllocator allocator, VulkanCommands* commands,
|
||||
VulkanStagePool& stagePool, VkFormat format, VkImageViewType viewType, uint8_t levels,
|
||||
uint8_t layerCount, VulkanLayout defaultLayout);
|
||||
uint8_t layerCount, VulkanLayout defaultLayout, bool isProtected);
|
||||
|
||||
struct ImageViewKey {
|
||||
VkImageSubresourceRange range; // 4 * 5 bytes
|
||||
@@ -70,6 +70,8 @@ struct VulkanTextureState : public VulkanResource {
|
||||
VkImage mTextureImage = VK_NULL_HANDLE;
|
||||
VulkanLayout mDefaultLayout;
|
||||
|
||||
bool mIsProtected = false;
|
||||
|
||||
// Track the image layout of each subresource using a sparse range map.
|
||||
utils::RangeMap<uint32_t, VulkanLayout> mSubresourceLayouts;
|
||||
|
||||
@@ -179,6 +181,11 @@ struct VulkanTexture : public HwTexture, VulkanResource {
|
||||
return state->mIsTransientAttachment;
|
||||
}
|
||||
|
||||
bool getIsProtected() const {
|
||||
VulkanTextureState const* state = getSharedState();
|
||||
return state->mIsProtected;
|
||||
}
|
||||
|
||||
bool transitionLayout(VulkanCommandBuffer* commands, VkImageSubresourceRange const& range,
|
||||
VulkanLayout newLayout);
|
||||
|
||||
|
||||
@@ -369,6 +369,10 @@ void VulkanDescriptorSetManager::bind(uint8_t setIndex, VulkanDescriptorSet* set
|
||||
mStashedSets[setIndex] = set;
|
||||
}
|
||||
|
||||
void VulkanDescriptorSetManager::unbind(uint8_t setIndex) {
|
||||
mStashedSets[setIndex] = nullptr;
|
||||
}
|
||||
|
||||
void VulkanDescriptorSetManager::commit(VulkanCommandBuffer* commands,
|
||||
VkPipelineLayout pipelineLayout, DescriptorSetMask const& setMask) {
|
||||
// setMask indicates the set of descriptor sets the driver wants to bind, curMask is the
|
||||
|
||||
@@ -61,6 +61,8 @@ public:
|
||||
|
||||
void bind(uint8_t setIndex, VulkanDescriptorSet* set, backend::DescriptorSetOffsetArray&& offsets);
|
||||
|
||||
void unbind(uint8_t setIndex);
|
||||
|
||||
void commit(VulkanCommandBuffer* commands, VkPipelineLayout pipelineLayout,
|
||||
DescriptorSetMask const& setMask);
|
||||
|
||||
|
||||
@@ -300,10 +300,10 @@ VkInstance createInstance(ExtensionSet const& requiredExts) {
|
||||
}
|
||||
|
||||
VkDevice createLogicalDevice(VkPhysicalDevice physicalDevice,
|
||||
VkPhysicalDeviceFeatures const& features, uint32_t graphicsQueueFamilyIndex,
|
||||
ExtensionSet const& deviceExtensions) {
|
||||
VkPhysicalDeviceFeatures2 const& features, uint32_t graphicsQueueFamilyIndex,
|
||||
uint32_t protectedGraphicsQueueFamilyIndex, ExtensionSet const& deviceExtensions) {
|
||||
VkDevice device;
|
||||
VkDeviceQueueCreateInfo deviceQueueCreateInfo[1] = {};
|
||||
VkDeviceQueueCreateInfo deviceQueueCreateInfo[2] = {};
|
||||
const float queuePriority[] = {1.0f};
|
||||
VkDeviceCreateInfo deviceCreateInfo = {};
|
||||
FixedCapacityVector<const char*> requestExtensions;
|
||||
@@ -314,22 +314,30 @@ VkDevice createLogicalDevice(VkPhysicalDevice physicalDevice,
|
||||
for (auto const& ext: deviceExtensions) {
|
||||
requestExtensions.push_back(ext.data());
|
||||
}
|
||||
deviceQueueCreateInfo->sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
|
||||
deviceQueueCreateInfo->queueFamilyIndex = graphicsQueueFamilyIndex;
|
||||
deviceQueueCreateInfo->queueCount = 1;
|
||||
deviceQueueCreateInfo->pQueuePriorities = &queuePriority[0];
|
||||
deviceQueueCreateInfo[0].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
|
||||
deviceQueueCreateInfo[0].queueFamilyIndex = graphicsQueueFamilyIndex;
|
||||
deviceQueueCreateInfo[0].queueCount = 1;
|
||||
deviceQueueCreateInfo[0].pQueuePriorities = &queuePriority[0];
|
||||
// Protected queue
|
||||
deviceQueueCreateInfo[1].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
|
||||
deviceQueueCreateInfo[1].flags = VK_DEVICE_QUEUE_CREATE_PROTECTED_BIT;
|
||||
deviceQueueCreateInfo[1].queueFamilyIndex = protectedGraphicsQueueFamilyIndex;
|
||||
deviceQueueCreateInfo[1].queueCount = 1;
|
||||
deviceQueueCreateInfo[1].pQueuePriorities = &queuePriority[0];
|
||||
|
||||
deviceCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
|
||||
deviceCreateInfo.queueCreateInfoCount = 1;
|
||||
bool const hasProtectedQueue = protectedGraphicsQueueFamilyIndex != INVALID_VK_INDEX;
|
||||
deviceCreateInfo.queueCreateInfoCount = hasProtectedQueue ? 2 : 1;
|
||||
deviceCreateInfo.pQueueCreateInfos = deviceQueueCreateInfo;
|
||||
|
||||
// We could simply enable all supported features, but since that may have performance
|
||||
// consequences let's just enable the features we need.
|
||||
VkPhysicalDeviceFeatures enabledFeatures{
|
||||
.depthClamp = features.depthClamp,
|
||||
.samplerAnisotropy = features.samplerAnisotropy,
|
||||
.textureCompressionETC2 = features.textureCompressionETC2,
|
||||
.textureCompressionBC = features.textureCompressionBC,
|
||||
.shaderClipDistance = features.shaderClipDistance,
|
||||
.depthClamp = features.features.depthClamp,
|
||||
.samplerAnisotropy = features.features.samplerAnisotropy,
|
||||
.textureCompressionETC2 = features.features.textureCompressionETC2,
|
||||
.textureCompressionBC = features.features.textureCompressionBC,
|
||||
.shaderClipDistance = features.features.shaderClipDistance,
|
||||
};
|
||||
|
||||
deviceCreateInfo.pEnabledFeatures = &enabledFeatures;
|
||||
@@ -360,6 +368,16 @@ VkDevice createLogicalDevice(VkPhysicalDevice physicalDevice,
|
||||
pNext = &multiview;
|
||||
}
|
||||
|
||||
VkPhysicalDeviceProtectedMemoryFeatures protectedMemory = {
|
||||
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES,
|
||||
};
|
||||
if (hasProtectedQueue) {
|
||||
// Enable protected memory, if requested.
|
||||
protectedMemory.protectedMemory = VK_TRUE;
|
||||
protectedMemory.pNext = pNext;
|
||||
pNext = &protectedMemory;
|
||||
}
|
||||
|
||||
deviceCreateInfo.pNext = pNext;
|
||||
|
||||
VkResult result = vkCreateDevice(physicalDevice, &deviceCreateInfo, VKALLOC, &device);
|
||||
@@ -406,13 +424,13 @@ FixedCapacityVector<VkQueueFamilyProperties> getPhysicalDeviceQueueFamilyPropert
|
||||
return queueFamiliesProperties;
|
||||
}
|
||||
|
||||
uint32_t identifyGraphicsQueueFamilyIndex(VkPhysicalDevice physicalDevice) {
|
||||
uint32_t identifyGraphicsQueueFamilyIndex(VkPhysicalDevice physicalDevice, VkQueueFlags flags) {
|
||||
const FixedCapacityVector<VkQueueFamilyProperties> queueFamiliesProperties
|
||||
= getPhysicalDeviceQueueFamilyPropertiesHelper(physicalDevice);
|
||||
uint32_t graphicsQueueFamilyIndex = INVALID_VK_INDEX;
|
||||
for (uint32_t j = 0; j < queueFamiliesProperties.size(); ++j) {
|
||||
VkQueueFamilyProperties props = queueFamiliesProperties[j];
|
||||
if (props.queueCount != 0 && props.queueFlags & VK_QUEUE_GRAPHICS_BIT) {
|
||||
if (props.queueCount != 0 && props.queueFlags & flags) {
|
||||
graphicsQueueFamilyIndex = j;
|
||||
break;
|
||||
}
|
||||
@@ -473,7 +491,8 @@ VkPhysicalDevice selectPhysicalDevice(VkInstance instance,
|
||||
// Does the device have any command queues that support graphics?
|
||||
// In theory, we should also ensure that the device supports presentation of our
|
||||
// particular VkSurface, but we don't have a VkSurface yet, so we'll skip this requirement.
|
||||
if (identifyGraphicsQueueFamilyIndex(candidateDevice) == INVALID_VK_INDEX) {
|
||||
if (identifyGraphicsQueueFamilyIndex(candidateDevice, VK_QUEUE_GRAPHICS_BIT)
|
||||
== INVALID_VK_INDEX) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -584,6 +603,9 @@ struct VulkanPlatformPrivate {
|
||||
uint32_t mGraphicsQueueFamilyIndex = INVALID_VK_INDEX;
|
||||
uint32_t mGraphicsQueueIndex = INVALID_VK_INDEX;
|
||||
VkQueue mGraphicsQueue = VK_NULL_HANDLE;
|
||||
uint32_t mProtectedGraphicsQueueFamilyIndex = INVALID_VK_INDEX;
|
||||
uint32_t mProtectedGraphicsQueueIndex = INVALID_VK_INDEX;
|
||||
VkQueue mProtectedGraphicsQueue = VK_NULL_HANDLE;
|
||||
VulkanContext mContext = {};
|
||||
|
||||
// We use a map to both map a handle (i.e. SwapChainPtr) to the concrete type and also to
|
||||
@@ -686,22 +708,45 @@ Driver* VulkanPlatform::createDriver(void* sharedContext,
|
||||
|
||||
printDeviceInfo(mImpl->mInstance, mImpl->mPhysicalDevice);
|
||||
|
||||
VkPhysicalDeviceProtectedMemoryFeatures queryProtectedMemoryFeatures = {
|
||||
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES,
|
||||
};
|
||||
// Chain to the pNext linked list
|
||||
queryProtectedMemoryFeatures.pNext = context.mPhysicalDeviceFeatures.pNext;
|
||||
context.mPhysicalDeviceFeatures.pNext = &queryProtectedMemoryFeatures;
|
||||
VkPhysicalDeviceProtectedMemoryProperties protectedMemoryProperties = {
|
||||
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_PROPERTIES,
|
||||
};
|
||||
protectedMemoryProperties.pNext = context.mPhysicalDeviceProperties.pNext;
|
||||
context.mPhysicalDeviceProperties.pNext = &protectedMemoryProperties;
|
||||
|
||||
// Initialize the following fields: physicalDeviceProperties, memoryProperties,
|
||||
// physicalDeviceFeatures, graphicsQueueFamilyIndex.
|
||||
vkGetPhysicalDeviceProperties(mImpl->mPhysicalDevice, &context.mPhysicalDeviceProperties);
|
||||
vkGetPhysicalDeviceFeatures(mImpl->mPhysicalDevice, &context.mPhysicalDeviceFeatures);
|
||||
vkGetPhysicalDeviceProperties2(mImpl->mPhysicalDevice, &context.mPhysicalDeviceProperties);
|
||||
vkGetPhysicalDeviceFeatures2(mImpl->mPhysicalDevice, &context.mPhysicalDeviceFeatures);
|
||||
vkGetPhysicalDeviceMemoryProperties(mImpl->mPhysicalDevice, &context.mMemoryProperties);
|
||||
|
||||
mImpl->mGraphicsQueueFamilyIndex
|
||||
= mImpl->mGraphicsQueueFamilyIndex == INVALID_VK_INDEX
|
||||
? identifyGraphicsQueueFamilyIndex(mImpl->mPhysicalDevice)
|
||||
? identifyGraphicsQueueFamilyIndex(mImpl->mPhysicalDevice,
|
||||
VK_QUEUE_GRAPHICS_BIT)
|
||||
: mImpl->mGraphicsQueueFamilyIndex;
|
||||
assert_invariant(mImpl->mGraphicsQueueFamilyIndex != INVALID_VK_INDEX);
|
||||
|
||||
// We know we need to allocate the protected version of the VK objects
|
||||
context.mProtectedMemorySupported =
|
||||
static_cast<bool>(queryProtectedMemoryFeatures.protectedMemory);
|
||||
if (context.mProtectedMemorySupported) {
|
||||
mImpl->mProtectedGraphicsQueueFamilyIndex
|
||||
= identifyGraphicsQueueFamilyIndex(mImpl->mPhysicalDevice,
|
||||
(VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_PROTECTED_BIT));
|
||||
assert_invariant(mImpl->mProtectedGraphicsQueueFamilyIndex != INVALID_VK_INDEX);
|
||||
}
|
||||
|
||||
// Only enable shaderClipDistance if we are doing instanced stereoscopic rendering.
|
||||
if (context.mPhysicalDeviceFeatures.shaderClipDistance == VK_TRUE
|
||||
if (context.mPhysicalDeviceFeatures.features.shaderClipDistance == VK_TRUE
|
||||
&& driverConfig.stereoscopicType != StereoscopicType::INSTANCED) {
|
||||
context.mPhysicalDeviceFeatures.shaderClipDistance = VK_FALSE;
|
||||
context.mPhysicalDeviceFeatures.features.shaderClipDistance = VK_FALSE;
|
||||
}
|
||||
|
||||
// At this point, we should have a family index that points to a family that has > 0 queues for
|
||||
@@ -711,6 +756,11 @@ Driver* VulkanPlatform::createDriver(void* sharedContext,
|
||||
mImpl->mGraphicsQueueIndex
|
||||
= mImpl->mGraphicsQueueIndex == INVALID_VK_INDEX ? 0 : mImpl->mGraphicsQueueIndex;
|
||||
|
||||
// Applying the same logic to the protected queue index (Not sure about shared context and protection)
|
||||
mImpl->mProtectedGraphicsQueueIndex
|
||||
= mImpl->mProtectedGraphicsQueueIndex == INVALID_VK_INDEX ? 0 :
|
||||
mImpl->mProtectedGraphicsQueueIndex;
|
||||
|
||||
ExtensionSet deviceExts;
|
||||
// If using a shared context, we do not assume any extensions.
|
||||
if (!mImpl->mSharedContext) {
|
||||
@@ -727,7 +777,8 @@ Driver* VulkanPlatform::createDriver(void* sharedContext,
|
||||
|
||||
mImpl->mDevice
|
||||
= mImpl->mDevice == VK_NULL_HANDLE ? createLogicalDevice(mImpl->mPhysicalDevice,
|
||||
context.mPhysicalDeviceFeatures, mImpl->mGraphicsQueueFamilyIndex, deviceExts)
|
||||
context.mPhysicalDeviceFeatures, mImpl->mGraphicsQueueFamilyIndex,
|
||||
mImpl->mProtectedGraphicsQueueFamilyIndex, deviceExts)
|
||||
: mImpl->mDevice;
|
||||
assert_invariant(mImpl->mDevice != VK_NULL_HANDLE);
|
||||
|
||||
@@ -735,6 +786,15 @@ Driver* VulkanPlatform::createDriver(void* sharedContext,
|
||||
&mImpl->mGraphicsQueue);
|
||||
assert_invariant(mImpl->mGraphicsQueue != VK_NULL_HANDLE);
|
||||
|
||||
if (context.mProtectedMemorySupported) {
|
||||
VkDeviceQueueInfo2 info = {};
|
||||
info.queueFamilyIndex = mImpl->mProtectedGraphicsQueueFamilyIndex;
|
||||
info.queueIndex = mImpl->mProtectedGraphicsQueueIndex;
|
||||
info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_INFO_2;
|
||||
info.flags = VK_DEVICE_QUEUE_CREATE_PROTECTED_BIT;
|
||||
vkGetDeviceQueue2(mImpl->mDevice, &info, &mImpl->mProtectedGraphicsQueue);
|
||||
}
|
||||
|
||||
// Store the extension support in the context
|
||||
context.mDebugUtilsSupported = setContains(instExts, VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
|
||||
context.mDebugMarkersSupported = setContains(deviceExts, VK_EXT_DEBUG_MARKER_EXTENSION_NAME);
|
||||
@@ -800,6 +860,10 @@ bool VulkanPlatform::hasResized(SwapChainPtr handle) {
|
||||
SWAPCHAIN_RET_FUNC(hasResized, handle, )
|
||||
}
|
||||
|
||||
bool VulkanPlatform::isProtected(SwapChainPtr handle) {
|
||||
SWAPCHAIN_RET_FUNC(isProtected, handle, )
|
||||
}
|
||||
|
||||
VkResult VulkanPlatform::recreate(SwapChainPtr handle) {
|
||||
SWAPCHAIN_RET_FUNC(recreate, handle, )
|
||||
}
|
||||
@@ -829,6 +893,13 @@ SwapChainPtr VulkanPlatform::createSwapChain(void* nativeWindow, uint64_t flags,
|
||||
flags |= SWAP_CHAIN_CONFIG_ENABLE_XCB;
|
||||
}
|
||||
|
||||
if (flags & backend::SWAP_CHAIN_CONFIG_PROTECTED_CONTENT) {
|
||||
if (!mImpl->mContext.mProtectedMemorySupported) {
|
||||
utils::slog.w << "protected swapchain requested, but VulkanPlatform does not support it"
|
||||
<< utils::io::endl;
|
||||
}
|
||||
}
|
||||
|
||||
auto [surface, fallbackExtent] = createVkSurfaceKHR(nativeWindow, mImpl->mInstance, flags);
|
||||
// The VulkanPlatformSurfaceSwapChain now `owns` the surface.
|
||||
VulkanPlatformSurfaceSwapChain* swapchain = new VulkanPlatformSurfaceSwapChain(mImpl->mContext,
|
||||
@@ -862,6 +933,18 @@ VkQueue VulkanPlatform::getGraphicsQueue() const noexcept {
|
||||
return mImpl->mGraphicsQueue;
|
||||
}
|
||||
|
||||
uint32_t VulkanPlatform::getProtectedGraphicsQueueFamilyIndex() const noexcept {
|
||||
return mImpl->mProtectedGraphicsQueueFamilyIndex;
|
||||
}
|
||||
|
||||
uint32_t VulkanPlatform::getProtectedGraphicsQueueIndex() const noexcept {
|
||||
return mImpl->mProtectedGraphicsQueueIndex;
|
||||
}
|
||||
|
||||
VkQueue VulkanPlatform::getProtectedGraphicsQueue() const noexcept {
|
||||
return mImpl->mProtectedGraphicsQueue;
|
||||
}
|
||||
|
||||
#undef SWAPCHAIN_RET_FUNC
|
||||
|
||||
}// namespace filament::backend
|
||||
|
||||
@@ -125,7 +125,8 @@ VulkanPlatformSurfaceSwapChain::VulkanPlatformSurfaceSwapChain(VulkanContext con
|
||||
mSurface(surface),
|
||||
mFallbackExtent(fallbackExtent),
|
||||
mUsesRGB((flags & backend::SWAP_CHAIN_CONFIG_SRGB_COLORSPACE) != 0),
|
||||
mHasStencil((flags & backend::SWAP_CHAIN_HAS_STENCIL_BUFFER) != 0) {
|
||||
mHasStencil((flags & backend::SWAP_CHAIN_HAS_STENCIL_BUFFER) != 0),
|
||||
mIsProtected((flags & backend::SWAP_CHAIN_CONFIG_PROTECTED_CONTENT) != 0) {
|
||||
assert_invariant(surface);
|
||||
create();
|
||||
}
|
||||
@@ -212,6 +213,8 @@ VkResult VulkanPlatformSurfaceSwapChain::create() {
|
||||
|
||||
VkSwapchainCreateInfoKHR const createInfo{
|
||||
.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
|
||||
.flags = mIsProtected ? VK_SWAPCHAIN_CREATE_PROTECTED_BIT_KHR :
|
||||
VkSwapchainCreateFlagsKHR(0),
|
||||
.surface = mSurface,
|
||||
.minImageCount = desiredImageCount,
|
||||
.imageFormat = surfaceFormat.format,
|
||||
@@ -246,13 +249,15 @@ VkResult VulkanPlatformSurfaceSwapChain::create() {
|
||||
mSwapChainBundle.depthFormat =
|
||||
selectDepthFormat(mContext.getAttachmentDepthStencilFormats(), mHasStencil);
|
||||
mSwapChainBundle.depth = createImage(mSwapChainBundle.extent, mSwapChainBundle.depthFormat);
|
||||
mSwapChainBundle.isProtected = mIsProtected;
|
||||
|
||||
FVK_LOGI << "vkCreateSwapchain"
|
||||
<< ": " << mSwapChainBundle.extent.width << "x" << mSwapChainBundle.extent.height << ", "
|
||||
<< surfaceFormat.format << ", " << surfaceFormat.colorSpace << ", "
|
||||
<< "swapchain-size=" << mSwapChainBundle.colors.size() << ", "
|
||||
<< "identity-transform=" << (caps.currentTransform == 1) << ", "
|
||||
<< "depth=" << mSwapChainBundle.depthFormat
|
||||
<< "depth=" << mSwapChainBundle.depthFormat << ", "
|
||||
<< "protected=" << mSwapChainBundle.isProtected
|
||||
<< io::endl;
|
||||
|
||||
VkSemaphoreCreateInfo const semaphoreCreateInfo = {
|
||||
@@ -317,6 +322,10 @@ bool VulkanPlatformSurfaceSwapChain::hasResized() {
|
||||
return !equivalent(mSwapChainBundle.extent, perceivedExtent);
|
||||
}
|
||||
|
||||
bool VulkanPlatformSurfaceSwapChain::isProtected() {
|
||||
return mIsProtected;
|
||||
}
|
||||
|
||||
// Non-virtual override
|
||||
VkResult VulkanPlatformSurfaceSwapChain::recreate() {
|
||||
destroy();
|
||||
|
||||
@@ -64,6 +64,11 @@ struct VulkanPlatformSwapChainImpl : public Platform::SwapChain {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Non-virtual override-able method
|
||||
bool isProtected() {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected:
|
||||
// Non-virtual override-able method
|
||||
void destroy();
|
||||
@@ -97,6 +102,9 @@ struct VulkanPlatformSurfaceSwapChain : public VulkanPlatformSwapChainImpl {
|
||||
// Non-virtual override-able method
|
||||
bool hasResized();
|
||||
|
||||
// Non-virtual override-able method
|
||||
bool isProtected();
|
||||
|
||||
protected:
|
||||
// Non-virtual override-able method
|
||||
void destroy();
|
||||
@@ -117,6 +125,7 @@ private:
|
||||
|
||||
bool mUsesRGB = false;
|
||||
bool mHasStencil = false;
|
||||
bool mIsProtected = false;
|
||||
bool mSuboptimal;
|
||||
};
|
||||
|
||||
|
||||
@@ -519,16 +519,17 @@ PostProcessManager::StructurePassOutput PostProcessManager::structure(FrameGraph
|
||||
Variant structureVariant(Variant::DEPTH_VARIANT);
|
||||
structureVariant.setPicking(config.picking);
|
||||
|
||||
auto out = resources.getRenderPassInfo();
|
||||
|
||||
bindPostProcessDescriptorSet(driver);
|
||||
|
||||
passBuilder.renderFlags(structureRenderFlags);
|
||||
passBuilder.variant(structureVariant);
|
||||
passBuilder.commandTypeFlags(RenderPass::CommandTypeFlags::SSAO);
|
||||
|
||||
RenderPass const pass{ passBuilder.build(mEngine) };
|
||||
RenderPass::execute(pass, mEngine, resources.getPassName(), out.target, out.params);
|
||||
RenderPass const pass{ passBuilder.build(mEngine, driver) };
|
||||
auto out = resources.getRenderPassInfo();
|
||||
driver.beginRenderPass(out.target, out.params);
|
||||
pass.getExecutor().execute(mEngine, driver);
|
||||
driver.endRenderPass();
|
||||
});
|
||||
|
||||
auto depth = structurePass->depth;
|
||||
@@ -678,8 +679,10 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::ssr(FrameGraph& fg,
|
||||
// generate all our drawing commands, except blended objects.
|
||||
passBuilder.commandTypeFlags(RenderPass::CommandTypeFlags::SCREEN_SPACE_REFLECTIONS);
|
||||
|
||||
RenderPass const pass{ passBuilder.build(mEngine) };
|
||||
RenderPass::execute(pass, mEngine, resources.getPassName(), out.target, out.params);
|
||||
RenderPass const pass{ passBuilder.build(mEngine, driver) };
|
||||
driver.beginRenderPass(out.target, out.params);
|
||||
pass.getExecutor().execute(mEngine, driver);
|
||||
driver.endRenderPass();
|
||||
});
|
||||
|
||||
return ssrPass->reflections;
|
||||
|
||||
+26
-35
@@ -68,7 +68,6 @@ namespace filament {
|
||||
using namespace backend;
|
||||
|
||||
RenderPassBuilder& RenderPassBuilder::customCommand(
|
||||
FEngine& engine,
|
||||
uint8_t channel,
|
||||
RenderPass::Pass pass,
|
||||
RenderPass::CustomCommand custom,
|
||||
@@ -76,17 +75,17 @@ RenderPassBuilder& RenderPassBuilder::customCommand(
|
||||
RenderPass::Executor::CustomCommandFn const& command) {
|
||||
if (!mCustomCommands.has_value()) {
|
||||
// construct the vector the first time
|
||||
mCustomCommands.emplace(engine.getPerRenderPassArena());
|
||||
mCustomCommands.emplace();
|
||||
}
|
||||
mCustomCommands->emplace_back(channel, pass, custom, order, command);
|
||||
return *this;
|
||||
}
|
||||
|
||||
RenderPass RenderPassBuilder::build(FEngine& engine) {
|
||||
RenderPass RenderPassBuilder::build(FEngine const& engine, backend::DriverApi& driver) const {
|
||||
assert_invariant(mRenderableSoa);
|
||||
assert_invariant(mScissorViewport.width <= std::numeric_limits<int32_t>::max());
|
||||
assert_invariant(mScissorViewport.height <= std::numeric_limits<int32_t>::max());
|
||||
return RenderPass{ engine, *this };
|
||||
return RenderPass{ engine, driver, *this };
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@@ -107,11 +106,11 @@ void RenderPass::DescriptorSetHandleDeleter::operator()(
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
RenderPass::RenderPass(FEngine& engine, RenderPassBuilder const& builder) noexcept
|
||||
RenderPass::RenderPass(FEngine const& engine, backend::DriverApi& driver,
|
||||
RenderPassBuilder const& builder) noexcept
|
||||
: mRenderableSoa(*builder.mRenderableSoa),
|
||||
mColorPassDescriptorSet(builder.mColorPassDescriptorSet),
|
||||
mScissorViewport(builder.mScissorViewport),
|
||||
mCustomCommands(engine.getPerRenderPassArena()) {
|
||||
mScissorViewport(builder.mScissorViewport) {
|
||||
|
||||
// compute the number of commands we need
|
||||
updateSummedPrimitiveCounts(
|
||||
@@ -127,10 +126,12 @@ RenderPass::RenderPass(FEngine& engine, RenderPassBuilder const& builder) noexce
|
||||
uint32_t const customCommandCount =
|
||||
builder.mCustomCommands.has_value() ? builder.mCustomCommands->size() : 0;
|
||||
|
||||
// FIXME: builder.mArena must be thread safe eventually
|
||||
Command* const commandBegin = builder.mArena.alloc<Command>(commandCount + customCommandCount);
|
||||
Command* commandEnd = commandBegin + (commandCount + customCommandCount);
|
||||
assert_invariant(commandBegin);
|
||||
|
||||
// FIXME: builder.mArena must be thread safe eventually
|
||||
if (UTILS_UNLIKELY(builder.mArena.getAllocator().isHeapAllocation(commandBegin))) {
|
||||
static bool sLogOnce = true;
|
||||
if (UTILS_UNLIKELY(sLogOnce)) {
|
||||
@@ -150,6 +151,7 @@ RenderPass::RenderPass(FEngine& engine, RenderPassBuilder const& builder) noexce
|
||||
builder.mCameraForwardVector);
|
||||
|
||||
if (builder.mCustomCommands.has_value()) {
|
||||
mCustomCommands.reserve(customCommandCount);
|
||||
Command* p = commandBegin + commandCount;
|
||||
for (auto const& [channel, passId, command, order, fn]: builder.mCustomCommands.value()) {
|
||||
appendCustomCommand(p++, channel, passId, command, order, fn);
|
||||
@@ -166,7 +168,9 @@ RenderPass::RenderPass(FEngine& engine, RenderPassBuilder const& builder) noexce
|
||||
stereoscopicEyeCount *= engine.getConfig().stereoscopicEyeCount;
|
||||
}
|
||||
commandEnd = resize(builder.mArena,
|
||||
instanceify(engine, commandBegin, commandEnd, stereoscopicEyeCount));
|
||||
instanceify(driver,
|
||||
engine.getPerRenderableDescriptorSetLayout().getHandle(),
|
||||
commandBegin, commandEnd, stereoscopicEyeCount));
|
||||
}
|
||||
|
||||
// these are `const` from this point on...
|
||||
@@ -182,7 +186,7 @@ RenderPass::Command* RenderPass::resize(Arena& arena, Command* const last) noexc
|
||||
return last;
|
||||
}
|
||||
|
||||
void RenderPass::appendCommands(FEngine& engine,
|
||||
void RenderPass::appendCommands(FEngine const& engine,
|
||||
Slice<Command> commands,
|
||||
utils::Range<uint32_t> const vr,
|
||||
CommandTypeFlags const commandTypeFlags,
|
||||
@@ -283,17 +287,8 @@ RenderPass::Command* RenderPass::sortCommands(
|
||||
return last;
|
||||
}
|
||||
|
||||
void RenderPass::execute(RenderPass const& pass,
|
||||
FEngine& engine, const char* name,
|
||||
backend::Handle<backend::HwRenderTarget> renderTarget,
|
||||
backend::RenderPassParams params) noexcept {
|
||||
DriverApi& driver = engine.getDriverApi();
|
||||
driver.beginRenderPass(renderTarget, params);
|
||||
pass.getExecutor().execute(engine, name);
|
||||
driver.endRenderPass();
|
||||
}
|
||||
|
||||
RenderPass::Command* RenderPass::instanceify(FEngine& engine,
|
||||
RenderPass::Command* RenderPass::instanceify(backend::DriverApi& driver,
|
||||
DescriptorSetLayoutHandle perRenderableDescriptorSetLayoutHandle,
|
||||
Command* curr, Command* const last,
|
||||
int32_t eyeCount) const noexcept {
|
||||
SYSTRACE_NAME("instanceify");
|
||||
@@ -352,8 +347,6 @@ RenderPass::Command* RenderPass::instanceify(FEngine& engine,
|
||||
if (UTILS_UNLIKELY(instanceCount > 1)) {
|
||||
drawCallsSavedCount += instanceCount - 1;
|
||||
|
||||
auto& driver = engine.getDriverApi();
|
||||
|
||||
// allocate our staging buffer only if needed
|
||||
if (UTILS_UNLIKELY(!stagingBuffer)) {
|
||||
// Create a temporary UBO for holding the per-renderable data of each primitive,
|
||||
@@ -382,8 +375,7 @@ RenderPass::Command* RenderPass::instanceify(FEngine& engine,
|
||||
// in this case we would need to preserve the default descriptor-set content).
|
||||
// This has the same lifetime as the UBO (see above).
|
||||
mInstancedDescriptorSetHandle = DescriptorSetSharedHandle{
|
||||
driver.createDescriptorSet(
|
||||
engine.getPerRenderableDescriptorSetLayout().getHandle()),
|
||||
driver.createDescriptorSet(perRenderableDescriptorSetLayoutHandle),
|
||||
driver
|
||||
};
|
||||
driver.updateDescriptorSetBuffer(mInstancedDescriptorSetHandle,
|
||||
@@ -418,10 +410,7 @@ RenderPass::Command* RenderPass::instanceify(FEngine& engine,
|
||||
if (UTILS_UNLIKELY(firstSentinel)) {
|
||||
//slog.d << "auto-instancing, saving " << drawCallsSavedCount << " draw calls, out of "
|
||||
// << count << io::endl;
|
||||
|
||||
// we have instanced primitives
|
||||
DriverApi& driver = engine.getDriverApi();
|
||||
|
||||
// copy our instanced ubo data
|
||||
driver.updateBufferObjectUnsynchronized(mInstancedUboHandle, {
|
||||
stagingBuffer, sizeof(PerRenderableData) * instancedPrimitiveOffset,
|
||||
@@ -866,8 +855,8 @@ void RenderPass::Executor::overrideScissor(backend::Viewport const& scissor) noe
|
||||
mScissor = scissor;
|
||||
}
|
||||
|
||||
void RenderPass::Executor::execute(FEngine& engine, const char*) const noexcept {
|
||||
execute(engine, mCommands.begin(), mCommands.end());
|
||||
void RenderPass::Executor::execute(FEngine const& engine, backend::DriverApi& driver) const noexcept {
|
||||
execute(engine, driver, mCommands.begin(), mCommands.end());
|
||||
}
|
||||
|
||||
UTILS_NOINLINE // no need to be inlined
|
||||
@@ -893,14 +882,12 @@ backend::Viewport RenderPass::Executor::applyScissorViewport(
|
||||
}
|
||||
|
||||
UTILS_NOINLINE // no need to be inlined
|
||||
void RenderPass::Executor::execute(FEngine& engine,
|
||||
const Command* first, const Command* last) const noexcept {
|
||||
void RenderPass::Executor::execute(FEngine const& engine, backend::DriverApi& driver,
|
||||
Command const* first, Command const* last) const noexcept {
|
||||
|
||||
SYSTRACE_CALL();
|
||||
SYSTRACE_CONTEXT();
|
||||
|
||||
DriverApi& driver = engine.getDriverApi();
|
||||
|
||||
size_t const capacity = engine.getMinCommandBufferSize();
|
||||
CircularBuffer const& circularBuffer = driver.getCircularBuffer();
|
||||
|
||||
@@ -965,7 +952,9 @@ void RenderPass::Executor::execute(FEngine& engine,
|
||||
// check we have enough capacity to write these commandCount commands, if not,
|
||||
// request a new CircularBuffer allocation of `capacity` bytes.
|
||||
if (UTILS_UNLIKELY(circularBuffer.getUsed() > capacity - commandSizeInBytes)) {
|
||||
engine.flush(); // TODO: we should use a "fast" flush if possible
|
||||
// FIXME: eventually we can't flush here because this will be a secondary
|
||||
// command buffer. We will need another solution for overflows.
|
||||
const_cast<FEngine&>(engine).flush();
|
||||
}
|
||||
|
||||
first--;
|
||||
@@ -1093,7 +1082,9 @@ void RenderPass::Executor::execute(FEngine& engine,
|
||||
// If the remaining space is less than half the capacity, we flush right away to
|
||||
// allow some headroom for commands that might come later.
|
||||
if (UTILS_UNLIKELY(circularBuffer.getUsed() > capacity / 2)) {
|
||||
engine.flush();
|
||||
// FIXME: eventually we can't flush here because this will be a secondary
|
||||
// command buffer.
|
||||
const_cast<FEngine&>(engine).flush();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+14
-19
@@ -32,6 +32,7 @@
|
||||
|
||||
#include <utils/Allocator.h>
|
||||
#include <utils/BitmaskEnum.h>
|
||||
#include <utils/FixedCapacityVector.h>
|
||||
#include <utils/Range.h>
|
||||
#include <utils/Slice.h>
|
||||
#include <utils/architecture.h>
|
||||
@@ -309,13 +310,6 @@ public:
|
||||
Command const* end() const noexcept { return mCommandEnd; }
|
||||
bool empty() const noexcept { return begin() == end(); }
|
||||
|
||||
// Helper to execute all the commands generated by this RenderPass
|
||||
static void execute(RenderPass const& pass,
|
||||
FEngine& engine, const char* name,
|
||||
backend::Handle<backend::HwRenderTarget> renderTarget,
|
||||
backend::RenderPassParams params) noexcept;
|
||||
|
||||
|
||||
class BufferObjectHandleDeleter {
|
||||
std::reference_wrapper<backend::DriverApi> driver;
|
||||
public:
|
||||
@@ -364,7 +358,8 @@ public:
|
||||
|
||||
Executor(RenderPass const& pass, Command const* b, Command const* e) noexcept;
|
||||
|
||||
void execute(FEngine& engine, const Command* first, const Command* last) const noexcept;
|
||||
void execute(FEngine const& engine, backend::DriverApi& driver,
|
||||
Command const* first, Command const* last) const noexcept;
|
||||
|
||||
static backend::Viewport applyScissorViewport(
|
||||
backend::Viewport const& scissorViewport,
|
||||
@@ -389,7 +384,7 @@ public:
|
||||
|
||||
void overrideScissor(backend::Viewport const& scissor) noexcept;
|
||||
|
||||
void execute(FEngine& engine, const char* name) const noexcept;
|
||||
void execute(FEngine const& engine, backend::DriverApi& driver) const noexcept;
|
||||
};
|
||||
|
||||
// returns a new executor for this pass
|
||||
@@ -404,11 +399,12 @@ public:
|
||||
private:
|
||||
friend class FRenderer;
|
||||
friend class RenderPassBuilder;
|
||||
RenderPass(FEngine& engine, RenderPassBuilder const& builder) noexcept;
|
||||
RenderPass(FEngine const& engine, backend::DriverApi& driver,
|
||||
RenderPassBuilder const& builder) noexcept;
|
||||
|
||||
// This is the main function of this class, this appends commands to the pass using
|
||||
// the current camera, geometry and flags set. This can be called multiple times if needed.
|
||||
void appendCommands(FEngine& engine,
|
||||
void appendCommands(FEngine const& engine,
|
||||
utils::Slice<Command> commands,
|
||||
utils::Range<uint32_t> visibleRenderables,
|
||||
CommandTypeFlags commandTypeFlags,
|
||||
@@ -430,7 +426,8 @@ private:
|
||||
Command* begin, Command* end) noexcept;
|
||||
|
||||
// instanceify commands then trims sentinels
|
||||
RenderPass::Command* instanceify(FEngine& engine,
|
||||
RenderPass::Command* instanceify(backend::DriverApi& driver,
|
||||
backend::DescriptorSetLayoutHandle perRenderableDescriptorSetLayoutHandle,
|
||||
Command* begin, Command* end,
|
||||
int32_t eyeCount) const noexcept;
|
||||
|
||||
@@ -470,8 +467,7 @@ private:
|
||||
mutable BufferObjectSharedHandle mInstancedUboHandle; // ubo for instanced primitives
|
||||
mutable DescriptorSetSharedHandle mInstancedDescriptorSetHandle; // a descriptor-set to hold the ubo
|
||||
// a vector for our custom commands
|
||||
using CustomCommandVector = std::vector<Executor::CustomCommandFn,
|
||||
utils::STLAllocator<Executor::CustomCommandFn, LinearAllocatorArena>>;
|
||||
using CustomCommandVector = utils::FixedCapacityVector<Executor::CustomCommandFn>;
|
||||
mutable CustomCommandVector mCustomCommands;
|
||||
};
|
||||
|
||||
@@ -497,11 +493,10 @@ class RenderPassBuilder {
|
||||
uint32_t,
|
||||
RenderPass::Executor::CustomCommandFn>;
|
||||
|
||||
using CustomCommandContainer = std::vector<CustomCommandRecord,
|
||||
utils::STLAllocator<CustomCommandRecord, LinearAllocatorArena>>;
|
||||
using CustomCommandContainer = std::vector<CustomCommandRecord>;
|
||||
|
||||
// we make this optional because it's not used often, and we don't want to have
|
||||
// to construct it by default.
|
||||
// to construct it by default. For the same reason we use a std::vector<>
|
||||
std::optional<CustomCommandContainer> mCustomCommands;
|
||||
|
||||
public:
|
||||
@@ -569,14 +564,14 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
RenderPassBuilder& customCommand(FEngine& engine,
|
||||
RenderPassBuilder& customCommand(
|
||||
uint8_t channel,
|
||||
RenderPass::Pass pass,
|
||||
RenderPass::CustomCommand custom,
|
||||
uint32_t order,
|
||||
const RenderPass::Executor::CustomCommandFn& command);
|
||||
|
||||
RenderPass build(FEngine& engine);
|
||||
RenderPass build(FEngine const& engine, backend::DriverApi& driver) const;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -251,7 +251,7 @@ RendererUtils::ColorPassOutput RendererUtils::colorPass(
|
||||
}
|
||||
|
||||
driver.beginRenderPass(out.target, out.params);
|
||||
passExecutor.execute(engine, resources.getPassName());
|
||||
passExecutor.execute(engine, driver);
|
||||
driver.endRenderPass();
|
||||
|
||||
// color pass is typically heavy, and we don't have much CPU work left after
|
||||
|
||||
@@ -1361,8 +1361,8 @@ math::float4 ShadowMap::getClampToEdgeCoords(ShadowMapInfo const& shadowMapInfo)
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
void ShadowMap::prepareCamera(Transaction const& transaction,
|
||||
FEngine& engine, const CameraInfo& cameraInfo) noexcept {
|
||||
ShadowMapDescriptorSet::prepareCamera(transaction, engine, cameraInfo);
|
||||
backend::DriverApi& driver, const CameraInfo& cameraInfo) noexcept {
|
||||
ShadowMapDescriptorSet::prepareCamera(transaction, driver, cameraInfo);
|
||||
ShadowMapDescriptorSet::prepareLodBias(transaction, 0.0f);
|
||||
}
|
||||
|
||||
@@ -1372,7 +1372,7 @@ void ShadowMap::prepareViewport(Transaction const& transaction,
|
||||
}
|
||||
|
||||
void ShadowMap::prepareTime(Transaction const& transaction,
|
||||
FEngine& engine, math::float4 const& userTime) noexcept {
|
||||
FEngine const& engine, math::float4 const& userTime) noexcept {
|
||||
ShadowMapDescriptorSet::prepareTime(transaction, engine, userTime);
|
||||
}
|
||||
|
||||
|
||||
@@ -193,11 +193,11 @@ public:
|
||||
using Transaction = ShadowMapDescriptorSet::Transaction;
|
||||
|
||||
static void prepareCamera(Transaction const& transaction,
|
||||
FEngine& engine, const CameraInfo& cameraInfo) noexcept;
|
||||
backend::DriverApi& driver, const CameraInfo& cameraInfo) noexcept;
|
||||
static void prepareViewport(Transaction const& transaction,
|
||||
backend::Viewport const& viewport) noexcept;
|
||||
static void prepareTime(Transaction const& transaction,
|
||||
FEngine& engine, math::float4 const& userTime) noexcept;
|
||||
FEngine const& engine, math::float4 const& userTime) noexcept;
|
||||
static void prepareShadowMapping(Transaction const& transaction,
|
||||
bool highPrecision) noexcept;
|
||||
static ShadowMapDescriptorSet::Transaction open(backend::DriverApi& driver) noexcept;
|
||||
|
||||
@@ -314,9 +314,10 @@ FrameGraphId<FrameGraphTexture> ShadowMapManager::render(FEngine& engine, FrameG
|
||||
// "read" from one of its resource (only writes), so the FrameGraph culls it.
|
||||
builder.sideEffect();
|
||||
},
|
||||
[this, &engine, &view, vsmShadowOptions,
|
||||
scene, mainCameraInfo, userTime, passBuilder = passBuilder](
|
||||
FrameGraphResources const&, auto const& data, DriverApi& driver) mutable {
|
||||
[=, passBuilder = passBuilder,
|
||||
&engine = const_cast<FEngine /*const*/ &>(engine), // FIXME: we want this const
|
||||
&view = const_cast<FView const&>(view)]
|
||||
(FrameGraphResources const&, auto const& data, DriverApi& driver) mutable {
|
||||
|
||||
// Note: we could almost parallel_for the loop below, the problem currently is
|
||||
// that updatePrimitivesLod() updates temporary global state.
|
||||
@@ -363,7 +364,7 @@ FrameGraphId<FrameGraphTexture> ShadowMapManager::render(FEngine& engine, FrameG
|
||||
const CameraInfo cameraInfo{ shadowMap.getCamera(), mainCameraInfo };
|
||||
|
||||
auto transaction = ShadowMap::open(driver);
|
||||
ShadowMap::prepareCamera(transaction, engine, cameraInfo);
|
||||
ShadowMap::prepareCamera(transaction, driver, cameraInfo);
|
||||
ShadowMap::prepareViewport(transaction, shadowMap.getViewport());
|
||||
ShadowMap::prepareTime(transaction, engine, userTime);
|
||||
ShadowMap::prepareShadowMapping(transaction,
|
||||
@@ -371,8 +372,8 @@ FrameGraphId<FrameGraphTexture> ShadowMapManager::render(FEngine& engine, FrameG
|
||||
shadowMap.commit(transaction, engine, driver);
|
||||
|
||||
// updatePrimitivesLod must be run before RenderPass::appendCommands.
|
||||
view.updatePrimitivesLod(engine,
|
||||
cameraInfo, scene->getRenderableData(), entry.range);
|
||||
FView::updatePrimitivesLod(scene->getRenderableData(),
|
||||
engine, cameraInfo, entry.range);
|
||||
|
||||
// generate and sort the commands for rendering the shadow map
|
||||
|
||||
@@ -394,7 +395,7 @@ FrameGraphId<FrameGraphTexture> ShadowMapManager::render(FEngine& engine, FrameG
|
||||
.visibilityMask(entry.visibilityMask)
|
||||
.geometry(scene->getRenderableData(), entry.range)
|
||||
.commandTypeFlags(RenderPass::CommandTypeFlags::SHADOW)
|
||||
.build(engine);
|
||||
.build(engine, driver);
|
||||
|
||||
entry.executor = pass.getExecutor();
|
||||
|
||||
@@ -525,7 +526,7 @@ FrameGraphId<FrameGraphTexture> ShadowMapManager::render(FEngine& engine, FrameG
|
||||
if (entry.shadowMap->hasVisibleShadows()) {
|
||||
entry.shadowMap->bind(driver);
|
||||
entry.executor.overrideScissor(entry.shadowMap->getScissor());
|
||||
entry.executor.execute(engine, "Shadow Pass");
|
||||
entry.executor.execute(engine, driver);
|
||||
}
|
||||
driver.endRenderPass();
|
||||
});
|
||||
@@ -791,9 +792,10 @@ void ShadowMapManager::prepareSpotShadowMap(ShadowMap& shadowMap, FEngine& engin
|
||||
}
|
||||
}
|
||||
|
||||
void ShadowMapManager::cullSpotShadowMap(ShadowMap const& shadowMap, FEngine& engine, FView& view,
|
||||
void ShadowMapManager::cullSpotShadowMap(ShadowMap const& shadowMap,
|
||||
FEngine const& engine, FView const& view,
|
||||
FScene::RenderableSoa& renderableData, utils::Range<uint32_t> range,
|
||||
FScene::LightSoa& lightData) noexcept {
|
||||
FScene::LightSoa const& lightData) noexcept {
|
||||
auto& lcm = engine.getLightManager();
|
||||
|
||||
const size_t lightIndex = shadowMap.getLightIndex();
|
||||
@@ -881,23 +883,23 @@ void ShadowMapManager::preparePointShadowMap(ShadowMap& shadowMap,
|
||||
}
|
||||
}
|
||||
|
||||
void ShadowMapManager::cullPointShadowMap(ShadowMap const& shadowMap, FView& view,
|
||||
void ShadowMapManager::cullPointShadowMap(ShadowMap const& shadowMap, FView const& view,
|
||||
FScene::RenderableSoa& renderableData, utils::Range<uint32_t> range,
|
||||
FScene::LightSoa& lightData) noexcept {
|
||||
FScene::LightSoa const& lightData) noexcept {
|
||||
|
||||
const uint8_t face = shadowMap.getFace();
|
||||
const size_t lightIndex = shadowMap.getLightIndex();
|
||||
uint8_t const face = shadowMap.getFace();
|
||||
size_t const lightIndex = shadowMap.getLightIndex();
|
||||
|
||||
// compute the frustum for this light
|
||||
// for spotlights, we cull shadow casters first because we already know the frustum,
|
||||
// this will help us find better near/far plane later
|
||||
const auto position = lightData.elementAt<FScene::POSITION_RADIUS>(lightIndex).xyz;
|
||||
const auto radius = lightData.elementAt<FScene::POSITION_RADIUS>(lightIndex).w;
|
||||
auto const position = lightData.elementAt<FScene::POSITION_RADIUS>(lightIndex).xyz;
|
||||
auto const radius = lightData.elementAt<FScene::POSITION_RADIUS>(lightIndex).w;
|
||||
|
||||
// compute shadow map frustum for culling
|
||||
const mat4f Mv = ShadowMap::getPointLightViewMatrix(TextureCubemapFace(face), position);
|
||||
const mat4f Mp = mat4f::perspective(90.0f, 1.0f, 0.01f, radius);
|
||||
const Frustum frustum{ math::highPrecisionMultiply(Mp, Mv) };
|
||||
mat4f const Mv = ShadowMap::getPointLightViewMatrix(TextureCubemapFace(face), position);
|
||||
mat4f const Mp = mat4f::perspective(90.0f, 1.0f, 0.01f, radius);
|
||||
Frustum const frustum{ math::highPrecisionMultiply(Mp, Mv) };
|
||||
|
||||
// Cull shadow casters
|
||||
float3 const* worldAABBCenter = renderableData.data<FScene::WORLD_AABB_CENTER>();
|
||||
|
||||
@@ -165,17 +165,17 @@ private:
|
||||
FScene::LightSoa& lightData, ShadowMap::SceneInfo const& sceneInfo) noexcept;
|
||||
|
||||
static void cullSpotShadowMap(ShadowMap const& map,
|
||||
FEngine& engine, FView& view,
|
||||
FEngine const& engine, FView const& view,
|
||||
FScene::RenderableSoa& renderableData, utils::Range<uint32_t> range,
|
||||
FScene::LightSoa& lightData) noexcept;
|
||||
FScene::LightSoa const& lightData) noexcept;
|
||||
|
||||
void preparePointShadowMap(ShadowMap& map,
|
||||
FEngine& engine, FView& view, CameraInfo const& mainCameraInfo,
|
||||
FScene::LightSoa& lightData) noexcept;
|
||||
|
||||
static void cullPointShadowMap(ShadowMap const& shadowMap, FView& view,
|
||||
static void cullPointShadowMap(ShadowMap const& shadowMap, FView const& view,
|
||||
FScene::RenderableSoa& renderableData, utils::Range<uint32_t> range,
|
||||
FScene::LightSoa& lightData) noexcept;
|
||||
FScene::LightSoa const& lightData) noexcept;
|
||||
|
||||
static void updateSpotVisibilityMasks(
|
||||
uint8_t visibleLayers,
|
||||
@@ -253,8 +253,8 @@ private:
|
||||
return const_cast<ShadowMapManager*>(this)->getCascadedShadowMap();
|
||||
}
|
||||
|
||||
utils::Slice<ShadowMap> getSpotShadowMaps() noexcept {
|
||||
ShadowMap* const p = &getShadowMap(CONFIG_MAX_SHADOW_CASCADES);
|
||||
utils::Slice<ShadowMap> getSpotShadowMaps() const noexcept {
|
||||
ShadowMap const* const p = &getShadowMap(CONFIG_MAX_SHADOW_CASCADES);
|
||||
return { p, mSpotShadowMapCount };
|
||||
}
|
||||
};
|
||||
|
||||
@@ -208,10 +208,18 @@ public:
|
||||
return mRenderableManager;
|
||||
}
|
||||
|
||||
FRenderableManager const& getRenderableManager() const noexcept {
|
||||
return mRenderableManager;
|
||||
}
|
||||
|
||||
FLightManager& getLightManager() noexcept {
|
||||
return mLightManager;
|
||||
}
|
||||
|
||||
FLightManager const& getLightManager() const noexcept {
|
||||
return mLightManager;
|
||||
}
|
||||
|
||||
FCameraManager& getCameraManager() noexcept {
|
||||
return mCameraManager;
|
||||
}
|
||||
@@ -423,8 +431,11 @@ public:
|
||||
|
||||
bool execute();
|
||||
|
||||
utils::JobSystem& getJobSystem() noexcept {
|
||||
return mJobSystem;
|
||||
utils::JobSystem& getJobSystem() const noexcept {
|
||||
// JobSystem is thread-safe, and it's always okay to return a non-const one,
|
||||
// it's conceptually the same as if we were holding a non-const reference, as opposed
|
||||
// to by-value class attribute.
|
||||
return const_cast<utils::JobSystem&>(mJobSystem);
|
||||
}
|
||||
|
||||
std::default_random_engine& getRandomEngine() {
|
||||
|
||||
@@ -346,8 +346,8 @@ FMaterial::FMaterial(FEngine& engine, const Material::Builder& builder,
|
||||
FMaterial::~FMaterial() noexcept = default;
|
||||
|
||||
void FMaterial::invalidate(Variant::type_t variantMask, Variant::type_t variantValue) noexcept {
|
||||
DriverApi& driverApi = mEngine.getDriverApi();
|
||||
if (mMaterialDomain == MaterialDomain::SURFACE) {
|
||||
DriverApi& driverApi = mEngine.getDriverApi();
|
||||
auto& cachedPrograms = mCachedPrograms;
|
||||
for (size_t k = 0, n = VARIANT_COUNT; k < n; ++k) {
|
||||
Variant const variant(k);
|
||||
@@ -377,7 +377,6 @@ void FMaterial::invalidate(Variant::type_t variantMask, Variant::type_t variantV
|
||||
}
|
||||
}
|
||||
} else if (mMaterialDomain == MaterialDomain::POST_PROCESS) {
|
||||
DriverApi& driverApi = mEngine.getDriverApi();
|
||||
auto& cachedPrograms = mCachedPrograms;
|
||||
for (size_t k = 0, n = POST_PROCESS_VARIANT_COUNT; k < n; ++k) {
|
||||
if ((k & variantMask) == variantValue) {
|
||||
|
||||
@@ -921,8 +921,8 @@ void FRenderer::renderJob(RootArenaScope& rootArenaScope, FView& view) {
|
||||
|
||||
// updatePrimitivesLod must be run before appendCommands and once for each set
|
||||
// of RenderPass::setCamera / RenderPass::setGeometry calls.
|
||||
view.updatePrimitivesLod(engine, cameraInfo,
|
||||
scene.getRenderableData(), view.getVisibleRenderables());
|
||||
FView::updatePrimitivesLod(scene.getRenderableData(),
|
||||
engine, cameraInfo, view.getVisibleRenderables());
|
||||
|
||||
passBuilder.camera(cameraInfo);
|
||||
passBuilder.geometry(scene.getRenderableData(), view.getVisibleRenderables());
|
||||
@@ -1025,8 +1025,10 @@ void FRenderer::renderJob(RootArenaScope& rootArenaScope, FView& view) {
|
||||
passBuilder.variant(pickingVariant);
|
||||
passBuilder.commandTypeFlags(RenderPass::CommandTypeFlags::DEPTH);
|
||||
|
||||
RenderPass const pass{ passBuilder.build(mEngine) };
|
||||
RenderPass::execute(pass, mEngine, resources.getPassName(), out.target, out.params);
|
||||
RenderPass const pass{ passBuilder.build(mEngine, driver) };
|
||||
driver.beginRenderPass(out.target, out.params);
|
||||
pass.getExecutor().execute(mEngine, driver);
|
||||
driver.endRenderPass();
|
||||
});
|
||||
picking = pickingRenderPass->picking;
|
||||
}
|
||||
@@ -1130,7 +1132,7 @@ void FRenderer::renderJob(RootArenaScope& rootArenaScope, FView& view) {
|
||||
|
||||
if (colorGradingConfigForColor.asSubpass) {
|
||||
// append color grading subpass after all other passes
|
||||
passBuilder.customCommand(engine, 3,
|
||||
passBuilder.customCommand(3,
|
||||
RenderPass::Pass::BLENDED,
|
||||
RenderPass::CustomCommand::EPILOG,
|
||||
0, [&ppm, &driver, colorGradingConfigForColor]() {
|
||||
@@ -1138,7 +1140,7 @@ void FRenderer::renderJob(RootArenaScope& rootArenaScope, FView& view) {
|
||||
});
|
||||
} else if (colorGradingConfig.customResolve) {
|
||||
// append custom resolve subpass after all other passes
|
||||
passBuilder.customCommand(engine, 3,
|
||||
passBuilder.customCommand(3,
|
||||
RenderPass::Pass::BLENDED,
|
||||
RenderPass::CustomCommand::EPILOG,
|
||||
0, [&ppm, &driver]() {
|
||||
@@ -1156,7 +1158,7 @@ void FRenderer::renderJob(RootArenaScope& rootArenaScope, FView& view) {
|
||||
passBuilder.renderFlags(renderFlags);
|
||||
}
|
||||
|
||||
RenderPass const pass{ passBuilder.build(engine) };
|
||||
RenderPass const pass{ passBuilder.build(engine, driver) };
|
||||
|
||||
FrameGraphTexture::Descriptor colorBufferDesc = {
|
||||
.width = config.physicalViewport.width,
|
||||
|
||||
@@ -1065,8 +1065,8 @@ inline void FView::computeLightCameraDistances(
|
||||
}
|
||||
}
|
||||
|
||||
void FView::updatePrimitivesLod(FEngine& engine, const CameraInfo&,
|
||||
FScene::RenderableSoa& renderableData, Range visible) noexcept {
|
||||
void FView::updatePrimitivesLod(FScene::RenderableSoa& renderableData,
|
||||
FEngine const& engine, CameraInfo const&, Range visible) noexcept {
|
||||
FRenderableManager const& rcm = engine.getRenderableManager();
|
||||
for (uint32_t const index : visible) {
|
||||
uint8_t const level = 0; // TODO: pick the proper level of detail
|
||||
|
||||
@@ -203,9 +203,9 @@ public:
|
||||
CameraInfo const& cameraInfo, math::float4 const& userTime,
|
||||
RenderPassBuilder const& passBuilder) noexcept;
|
||||
|
||||
void updatePrimitivesLod(
|
||||
FEngine& engine, const CameraInfo& camera,
|
||||
FScene::RenderableSoa& renderableData, Range visible) noexcept;
|
||||
static void updatePrimitivesLod(FScene::RenderableSoa& renderableData,
|
||||
FEngine const& engine, CameraInfo const& camera,
|
||||
Range visible) noexcept;
|
||||
|
||||
void setShadowingEnabled(bool enabled) noexcept { mShadowingEnabled = enabled; }
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@ PerViewUib& ShadowMapDescriptorSet::edit(Transaction const& transaction) noexcep
|
||||
}
|
||||
|
||||
void ShadowMapDescriptorSet::prepareCamera(Transaction const& transaction,
|
||||
FEngine& engine, const CameraInfo& camera) noexcept {
|
||||
backend::DriverApi& driver, const CameraInfo& camera) noexcept {
|
||||
mat4f const& viewFromWorld = camera.view;
|
||||
mat4f const& worldFromView = camera.model;
|
||||
mat4f const& clipFromView = camera.projection;
|
||||
@@ -85,7 +85,7 @@ void ShadowMapDescriptorSet::prepareCamera(Transaction const& transaction,
|
||||
|
||||
// with a clip-space of [-w, w] ==> z' = -z
|
||||
// with a clip-space of [0, w] ==> z' = (w - z)/2
|
||||
s.clipControl = engine.getDriverApi().getClipSpaceParams();
|
||||
s.clipControl = driver.getClipSpaceParams();
|
||||
}
|
||||
|
||||
void ShadowMapDescriptorSet::prepareLodBias(Transaction const& transaction, float bias) noexcept {
|
||||
@@ -103,7 +103,7 @@ void ShadowMapDescriptorSet::prepareViewport(Transaction const& transaction,
|
||||
}
|
||||
|
||||
void ShadowMapDescriptorSet::prepareTime(Transaction const& transaction,
|
||||
FEngine& engine, math::float4 const& userTime) noexcept {
|
||||
FEngine const& engine, math::float4 const& userTime) noexcept {
|
||||
auto& s = edit(transaction);
|
||||
const uint64_t oneSecondRemainder = engine.getEngineTime().count() % 1'000'000'000;
|
||||
const float fraction = float(double(oneSecondRemainder) / 1'000'000'000.0);
|
||||
|
||||
@@ -56,7 +56,7 @@ public:
|
||||
void terminate(backend::DriverApi& driver);
|
||||
|
||||
static void prepareCamera(Transaction const& transaction,
|
||||
FEngine& engine, const CameraInfo& camera) noexcept;
|
||||
backend::DriverApi& driver, const CameraInfo& camera) noexcept;
|
||||
|
||||
static void prepareLodBias(Transaction const& transaction,
|
||||
float bias) noexcept;
|
||||
@@ -65,7 +65,7 @@ public:
|
||||
backend::Viewport const& viewport) noexcept;
|
||||
|
||||
static void prepareTime(Transaction const& transaction,
|
||||
FEngine& engine, math::float4 const& userTime) noexcept;
|
||||
FEngine const& engine, math::float4 const& userTime) noexcept;
|
||||
|
||||
static void prepareShadowMapping(Transaction const& transaction,
|
||||
bool highPrecision) noexcept;
|
||||
|
||||
Reference in New Issue
Block a user