Compare commits
51 Commits
bjd/add-mi
...
serge/vulk
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
531bfd6f6e | ||
|
|
db272484f9 | ||
|
|
9dadf400d2 | ||
|
|
16c7a3c968 | ||
|
|
626f338cba | ||
|
|
4e05cd73c6 | ||
|
|
49f9708312 | ||
|
|
2791195a92 | ||
|
|
65f78c06bb | ||
|
|
71175ee410 | ||
|
|
c9b310450c | ||
|
|
54c636d54c | ||
|
|
f503205be2 | ||
|
|
02106110fe | ||
|
|
5a0f78d915 | ||
|
|
f548c588d9 | ||
|
|
487fb273f1 | ||
|
|
111ac62d2f | ||
|
|
2fac13e154 | ||
|
|
bcae04c9ef | ||
|
|
55fc91b35f | ||
|
|
ff2827b226 | ||
|
|
13e1d2a042 | ||
|
|
b09cbaf0db | ||
|
|
b570d489e3 | ||
|
|
7f7daddbfa | ||
|
|
cfe6a423d3 | ||
|
|
ba99844f22 | ||
|
|
ea4c20ec2c | ||
|
|
0a661c1f3c | ||
|
|
021c4f6691 | ||
|
|
be6b6ae7be | ||
|
|
ad3a5b70b6 | ||
|
|
80803f9693 | ||
|
|
3b0e44c9a3 | ||
|
|
c5c2d42467 | ||
|
|
ff145f6ccf | ||
|
|
48bb10a4b5 | ||
|
|
01a2480175 | ||
|
|
9e921936c6 | ||
|
|
8bc4d3a9df | ||
|
|
0fdf1cac1d | ||
|
|
387942cc39 | ||
|
|
c81cedd887 | ||
|
|
abe8a49d17 | ||
|
|
96cba96058 | ||
|
|
4fccd957db | ||
|
|
d49554d5ce | ||
|
|
867161773e | ||
|
|
e2658506f6 | ||
|
|
6218164f79 |
@@ -214,6 +214,14 @@ if (FILAMENT_SUPPORTS_VULKAN)
|
||||
src/vulkan/VulkanMemory.h
|
||||
src/vulkan/VulkanPipelineCache.cpp
|
||||
src/vulkan/VulkanPipelineCache.h
|
||||
src/vulkan/VulkanPipelineStateSerializer.cpp
|
||||
src/vulkan/VulkanPipelineStateSerializer.h
|
||||
src/vulkan/VulkanSamplerStateSerializer.h
|
||||
src/vulkan/VulkanSamplerStateSerializer.cpp
|
||||
src/vulkan/VulkanRenderPassStateSerializer.h
|
||||
src/vulkan/VulkanRenderPassStateSerializer.cpp
|
||||
src/vulkan/VulkanDescriptorSetLayoutSerializer.h
|
||||
src/vulkan/VulkanDescriptorSetLayoutSerializer.cpp
|
||||
src/vulkan/VulkanPipelineLayoutCache.cpp
|
||||
src/vulkan/VulkanPipelineLayoutCache.h
|
||||
src/vulkan/VulkanQueryManager.cpp
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
|
||||
#include "VulkanDescriptorSetLayoutCache.h"
|
||||
#include "VulkanDescriptorSetLayoutSerializer.h"
|
||||
|
||||
#include "VulkanHandles.h"
|
||||
|
||||
@@ -100,22 +101,32 @@ uint32_t appendSamplerBindings(VkDescriptorSetLayoutBinding* toBind,
|
||||
return count;
|
||||
}
|
||||
|
||||
uint64_t computeImmutableSamplerHash(utils::FixedCapacityVector<VkSampler> const& samplers) {
|
||||
uint64_t computeImmutableSamplerHash(utils::FixedCapacityVector<VkSampler> const& samplers, VulkanSamplerCache* cache) {
|
||||
size_t const size = samplers.size();
|
||||
if (size == 0) {
|
||||
return 0;
|
||||
} else if (size == 1) {
|
||||
return (uint64_t) samplers[0];
|
||||
}
|
||||
return utils::hash::murmur3((uint32_t*) samplers.data(), samplers.size() * 2, 0);
|
||||
|
||||
utils::FixedCapacityVector<uint32_t> samplerHash;
|
||||
if (size > 0) {
|
||||
samplerHash.reserve(MAX_SAMPLER_COUNT);
|
||||
for (auto sampler : samplers) {
|
||||
samplerHash.push_back(cache->getKey(sampler));
|
||||
}
|
||||
}
|
||||
|
||||
if (size == 1) {
|
||||
return (uint64_t) samplerHash[0];
|
||||
}
|
||||
return utils::hash::murmur3((uint32_t*) samplerHash.data(), samplerHash.size() * 2, 0);
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
VulkanDescriptorSetLayoutCache::VulkanDescriptorSetLayoutCache(VkDevice device,
|
||||
fvkmemory::ResourceManager* resourceManager)
|
||||
fvkmemory::ResourceManager* resourceManager, VulkanSamplerCache* cache)
|
||||
: mDevice(device),
|
||||
mResourceManager(resourceManager) {}
|
||||
mResourceManager(resourceManager), mSamplerCache(cache) {}
|
||||
|
||||
VulkanDescriptorSetLayoutCache::~VulkanDescriptorSetLayoutCache() = default;
|
||||
|
||||
@@ -131,7 +142,7 @@ VkDescriptorSetLayout VulkanDescriptorSetLayoutCache::getVkLayout(
|
||||
utils::FixedCapacityVector<VkSampler> immutableSamplers) {
|
||||
LayoutKey key = {
|
||||
.bitmask = bitmasks,
|
||||
.immutableSamplerHash = computeImmutableSamplerHash(immutableSamplers),
|
||||
.immutableSamplerHash = computeImmutableSamplerHash(immutableSamplers, mSamplerCache),
|
||||
};
|
||||
if (auto itr = mVkLayouts.find(key); itr != mVkLayouts.end()) {
|
||||
return itr->second;
|
||||
@@ -153,9 +164,20 @@ VkDescriptorSetLayout VulkanDescriptorSetLayoutCache::getVkLayout(
|
||||
.bindingCount = count,
|
||||
.pBindings = toBind,
|
||||
};
|
||||
LayoutKeyHashFn hashFunc;
|
||||
uint32_t hashedKey = hashFunc(key);
|
||||
utils::FixedCapacityVector<uint32_t> immutableSamplersHashes;
|
||||
immutableSamplersHashes.reserve(MAX_SAMPLER_COUNT);
|
||||
for (auto sampler: immutableSamplers) {
|
||||
immutableSamplersHashes.push_back(mSamplerCache->getKey(sampler));
|
||||
}
|
||||
VulkanDescriptorSetLayoutSerializer setSer(dlinfo, immutableSamplersHashes, hashedKey);
|
||||
|
||||
VkDescriptorSetLayout vklayout;
|
||||
vkCreateDescriptorSetLayout(mDevice, &dlinfo, VKALLOC, &vklayout);
|
||||
mVkLayouts[key] = vklayout;
|
||||
|
||||
mLayoutToKey[vklayout] = hashedKey;
|
||||
return vklayout;
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,8 @@
|
||||
|
||||
#include "VulkanHandles.h"
|
||||
|
||||
#include "VulkanSamplerCache.h"
|
||||
|
||||
#include "vulkan/memory/ResourcePointer.h"
|
||||
|
||||
#include <backend/DriverEnums.h>
|
||||
@@ -35,7 +37,8 @@ namespace filament::backend {
|
||||
|
||||
class VulkanDescriptorSetLayoutCache {
|
||||
public:
|
||||
VulkanDescriptorSetLayoutCache(VkDevice device, fvkmemory::ResourceManager* resourceManager);
|
||||
VulkanDescriptorSetLayoutCache(VkDevice device, fvkmemory::ResourceManager* resourceManager,
|
||||
VulkanSamplerCache* cache);
|
||||
~VulkanDescriptorSetLayoutCache();
|
||||
|
||||
void terminate() noexcept;
|
||||
@@ -48,10 +51,19 @@ public:
|
||||
VkDescriptorSetLayout getVkLayout(VulkanDescriptorSetLayout::Bitmask const& bitmasks,
|
||||
fvkutils::SamplerBitmask externalSamplers,
|
||||
utils::FixedCapacityVector<VkSampler> immutableSamplers = {});
|
||||
uint32_t getKey(VkDescriptorSetLayout layout) {
|
||||
uint32_t key = 0;
|
||||
auto iter = mLayoutToKey.find(layout);
|
||||
if (iter != mLayoutToKey.end()) {
|
||||
key = iter->second;
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
private:
|
||||
VkDevice mDevice;
|
||||
fvkmemory::ResourceManager* mResourceManager;
|
||||
VulkanSamplerCache* mSamplerCache;
|
||||
|
||||
struct LayoutKey {
|
||||
// this describes the layout using bitset.
|
||||
@@ -69,6 +81,7 @@ private:
|
||||
};
|
||||
|
||||
tsl::robin_map<LayoutKey, VkDescriptorSetLayout, LayoutKeyHashFn, LayoutKeyEqual> mVkLayouts;
|
||||
std::map<VkDescriptorSetLayout, uint32_t> mLayoutToKey;
|
||||
};
|
||||
|
||||
} // namespace filament::backend
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
#include "VulkanDescriptorSetLayoutSerializer.h"
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <utils/Hash.h>
|
||||
|
||||
namespace filament::backend {
|
||||
VulkanDescriptorSetLayoutSerializer::VulkanDescriptorSetLayoutSerializer(
|
||||
const VkDescriptorSetLayoutCreateInfo& info,
|
||||
utils::FixedCapacityVector<uint32_t> immutableSamplers, uint32_t hash) {
|
||||
std::stringstream filename;
|
||||
filename << "descriptor_set_layout_" << hash << ".json";
|
||||
|
||||
std::ofstream file(filename.str());
|
||||
if (file.is_open()) {
|
||||
std::stringstream buffer;
|
||||
buffer << "[" << std::endl;
|
||||
for (uint32_t i = 0; i < info.bindingCount; ++i) {
|
||||
buffer << "{" << std::endl;
|
||||
buffer << "\"binding\":" << info.pBindings[i].binding << "," << std::endl;
|
||||
buffer << "\"descriptor_type\":" << info.pBindings[i].descriptorType << "," << std::endl;
|
||||
buffer << "\"stage_flags\":" << info.pBindings[i].stageFlags;
|
||||
if (immutableSamplers.size()) {
|
||||
buffer << "," << std::endl;
|
||||
buffer << "\"immutable_samplers\":[" << std::endl;
|
||||
for (uint32_t i = 0; i < immutableSamplers.size(); ++i) {
|
||||
buffer << immutableSamplers[i];
|
||||
if (i < immutableSamplers.size() - 1) {
|
||||
buffer << ",";
|
||||
}
|
||||
}
|
||||
buffer << "]";
|
||||
}
|
||||
buffer << std::endl;
|
||||
buffer << "}";
|
||||
if (i < info.bindingCount - 1) {
|
||||
buffer << ",";
|
||||
}
|
||||
buffer << std::endl;
|
||||
}
|
||||
buffer << "]" << std::endl;
|
||||
|
||||
file << buffer.str();
|
||||
}
|
||||
file.close();
|
||||
}
|
||||
|
||||
VulkanPipelineLayoutSerializer::VulkanPipelineLayoutSerializer(
|
||||
const VkPipelineLayoutCreateInfo& info, VulkanDescriptorSetLayoutCache* cache,
|
||||
uint32_t hash) {
|
||||
std::stringstream filename;
|
||||
filename << "pipeline_layout_" << hash << ".json";
|
||||
std::ofstream file(filename.str());
|
||||
if (file.is_open()) {
|
||||
std::stringstream buffer;
|
||||
buffer << "{" << std::endl;
|
||||
buffer << "\"flags\":" << info.flags << "," << std::endl;
|
||||
|
||||
buffer << "\"layouts\":[" << std::endl;
|
||||
for (uint32_t i = 0; i < info.setLayoutCount; ++i) {
|
||||
buffer << cache->getKey(info.pSetLayouts[i]);
|
||||
if (i < info.setLayoutCount - 1) {
|
||||
buffer << ",";
|
||||
}
|
||||
}
|
||||
buffer << "]," << std::endl;
|
||||
|
||||
buffer << "\"push_constants\":[" << std::endl;
|
||||
for (uint32_t i = 0; i < info.pushConstantRangeCount; ++i) {
|
||||
buffer << "{" << std::endl;
|
||||
buffer << "\"stage_flags\":" << info.pPushConstantRanges[i].stageFlags << "," << std::endl;
|
||||
buffer << "\"offset\":" << info.pPushConstantRanges[i].offset << ","
|
||||
<< std::endl;
|
||||
buffer << "\"size\":" << info.pPushConstantRanges[i].size
|
||||
<< std::endl;
|
||||
buffer << "}" << std::endl;
|
||||
if (i < info.pushConstantRangeCount - 1) {
|
||||
buffer << ",";
|
||||
}
|
||||
}
|
||||
buffer << "]" << std::endl;
|
||||
|
||||
buffer << "}" << std::endl;
|
||||
file << buffer.str();
|
||||
}
|
||||
file.close();
|
||||
}
|
||||
} // namespace filament::backend
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef TNT_FILAMENT_BACKEND_VULKANDESCRIPTORSETLAYOUTSERIALIZER_H
|
||||
#define TNT_FILAMENT_BACKEND_VULKANDESCRIPTORSETLAYOUTSERIALIZER_H
|
||||
|
||||
#include "VulkanPipelineLayoutCache.h"
|
||||
#include "VulkanYcbcrConversionCache.h"
|
||||
#include <backend/DriverEnums.h>
|
||||
|
||||
#include <bluevk/BlueVK.h>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
class VulkanDescriptorSetLayoutSerializer {
|
||||
public:
|
||||
VulkanDescriptorSetLayoutSerializer(VulkanDescriptorSetLayoutSerializer const&) = delete;
|
||||
VulkanDescriptorSetLayoutSerializer& operator=(
|
||||
VulkanDescriptorSetLayoutSerializer const&) = delete;
|
||||
|
||||
VulkanDescriptorSetLayoutSerializer(const VkDescriptorSetLayoutCreateInfo& info,
|
||||
utils::FixedCapacityVector<uint32_t> immutableSamplers,
|
||||
uint32_t hash);
|
||||
};
|
||||
|
||||
class VulkanPipelineLayoutSerializer {
|
||||
public:
|
||||
VulkanPipelineLayoutSerializer(VulkanPipelineLayoutSerializer const&) = delete;
|
||||
VulkanPipelineLayoutSerializer& operator=(VulkanPipelineLayoutSerializer const&) = delete;
|
||||
|
||||
VulkanPipelineLayoutSerializer(const VkPipelineLayoutCreateInfo& layout,
|
||||
VulkanDescriptorSetLayoutCache* cache, uint32_t hash);
|
||||
};
|
||||
|
||||
} // namespace filament::backend
|
||||
|
||||
#endif // TNT_FILAMENT_BACKEND_VULKANDESCRIPTORSETLAYOUTSERIALIZER_H
|
||||
@@ -230,16 +230,16 @@ VulkanDriver::VulkanDriver(VulkanPlatform* platform, VulkanContext& context,
|
||||
mCommands(mPlatform->getDevice(), mPlatform->getGraphicsQueue(),
|
||||
mPlatform->getGraphicsQueueFamilyIndex(), mPlatform->getProtectedGraphicsQueue(),
|
||||
mPlatform->getProtectedGraphicsQueueFamilyIndex(), mContext, &mSemaphoreManager),
|
||||
mPipelineLayoutCache(mPlatform->getDevice()),
|
||||
mPipelineCache(mPlatform->getDevice()),
|
||||
mStagePool(mAllocator, &mResourceManager, &mCommands, &mContext.getPhysicalDeviceLimits()),
|
||||
mBufferCache(mContext, mResourceManager, mAllocator),
|
||||
mFramebufferCache(mPlatform->getDevice()),
|
||||
mYcbcrConversionCache(mPlatform->getDevice()),
|
||||
mSamplerCache(mPlatform->getDevice()),
|
||||
mSamplerCache(mPlatform->getDevice(), &mYcbcrConversionCache),
|
||||
mBlitter(mPlatform->getPhysicalDevice(), &mCommands),
|
||||
mReadPixels(mPlatform->getDevice()),
|
||||
mDescriptorSetLayoutCache(mPlatform->getDevice(), &mResourceManager),
|
||||
mDescriptorSetLayoutCache(mPlatform->getDevice(), &mResourceManager, &mSamplerCache),
|
||||
mPipelineLayoutCache(mPlatform->getDevice(), &mDescriptorSetLayoutCache),
|
||||
mDescriptorSetCache(mPlatform->getDevice(), &mResourceManager),
|
||||
mQueryManager(mPlatform->getDevice()),
|
||||
mExternalImageManager(platform, &mSamplerCache, &mYcbcrConversionCache, &mDescriptorSetCache,
|
||||
@@ -1666,7 +1666,7 @@ void VulkanDriver::beginRenderPass(Handle<HwRenderTarget> rth, const RenderPassP
|
||||
rpkey.subpassMask = uint8_t(params.subpassMask);
|
||||
|
||||
VkRenderPass renderPass = mFramebufferCache.getRenderPass(rpkey);
|
||||
mPipelineCache.bindRenderPass(renderPass, 0);
|
||||
mPipelineCache.bindRenderPass(renderPass, mFramebufferCache.getRenderPassKey(renderPass), 0);
|
||||
|
||||
// Create the VkFramebuffer or fetch it from cache.
|
||||
VulkanFboCache::FboKey fbkey = rt->getFboKey();
|
||||
@@ -1785,6 +1785,7 @@ void VulkanDriver::nextSubpass(int) {
|
||||
VK_SUBPASS_CONTENTS_INLINE);
|
||||
|
||||
mPipelineCache.bindRenderPass(mCurrentRenderPass.renderPass,
|
||||
mFramebufferCache.getRenderPassKey(mCurrentRenderPass.renderPass),
|
||||
++mCurrentRenderPass.currentSubpass);
|
||||
|
||||
if (mCurrentRenderPass.params.subpassMask & 0x1) {
|
||||
@@ -2160,7 +2161,8 @@ void VulkanDriver::bindPipelineImpl(PipelineState const& pipelineState,
|
||||
mPipelineState.pipelineLayout = pipelineLayout;
|
||||
mPipelineState.descriptorSetMask = descriptorSetMask;
|
||||
|
||||
mPipelineCache.bindLayout(pipelineLayout);
|
||||
auto key = mPipelineLayoutCache.getKey(pipelineLayout);
|
||||
mPipelineCache.bindLayout(pipelineLayout, key);
|
||||
mPipelineCache.bindPipeline(mCurrentRenderPass.commandBuffer);
|
||||
}
|
||||
|
||||
|
||||
@@ -148,7 +148,6 @@ private:
|
||||
|
||||
VulkanSemaphoreManager mSemaphoreManager;
|
||||
VulkanCommands mCommands;
|
||||
VulkanPipelineLayoutCache mPipelineLayoutCache;
|
||||
VulkanPipelineCache mPipelineCache;
|
||||
VulkanStagePool mStagePool;
|
||||
VulkanBufferCache mBufferCache;
|
||||
@@ -158,6 +157,7 @@ private:
|
||||
VulkanBlitter mBlitter;
|
||||
VulkanReadPixels mReadPixels;
|
||||
VulkanDescriptorSetLayoutCache mDescriptorSetLayoutCache;
|
||||
VulkanPipelineLayoutCache mPipelineLayoutCache;
|
||||
VulkanDescriptorSetCache mDescriptorSetCache;
|
||||
VulkanQueryManager mQueryManager;
|
||||
VulkanExternalImageManager mExternalImageManager;
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
|
||||
#include "VulkanFboCache.h"
|
||||
#include "VulkanRenderPassStateSerializer.h"
|
||||
|
||||
#include "VulkanConstants.h"
|
||||
#include "vulkan/utils/Image.h"
|
||||
@@ -69,6 +70,15 @@ VulkanFboCache::~VulkanFboCache() {
|
||||
<< "Please explicitly call terminate() while the VkDevice is still alive.";
|
||||
}
|
||||
|
||||
uint32_t VulkanFboCache::getRenderPassKey(VkRenderPass pass) noexcept {
|
||||
uint32_t key = 0;
|
||||
auto iter = mRenderPassToKey.find(pass);
|
||||
if (iter != mRenderPassToKey.end()) {
|
||||
key = iter->second;
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
VkFramebuffer VulkanFboCache::getFramebuffer(FboKey const& config) noexcept {
|
||||
FboMap::iterator iter = mFramebufferCache.find(config);
|
||||
if (UTILS_LIKELY(iter != mFramebufferCache.end() && iter->second.handle != VK_NULL_HANDLE)) {
|
||||
@@ -117,6 +127,7 @@ VkFramebuffer VulkanFboCache::getFramebuffer(FboKey const& config) noexcept {
|
||||
VkResult error = vkCreateFramebuffer(mDevice, &info, VKALLOC, &framebuffer);
|
||||
FILAMENT_CHECK_POSTCONDITION(error == VK_SUCCESS) << "Unable to create framebuffer."
|
||||
<< " error=" << static_cast<int32_t>(error);
|
||||
|
||||
mFramebufferCache[config] = {framebuffer, mCurrentTime};
|
||||
return framebuffer;
|
||||
}
|
||||
@@ -326,6 +337,12 @@ VkRenderPass VulkanFboCache::getRenderPass(RenderPassKey const& config) noexcept
|
||||
VkResult error = vkCreateRenderPass(mDevice, &renderPassInfo, VKALLOC, &renderPass);
|
||||
FILAMENT_CHECK_POSTCONDITION(error == VK_SUCCESS) << "Unable to create render pass."
|
||||
<< " error=" << error;
|
||||
|
||||
RenderPassHash hashFunc;
|
||||
uint32_t key = hashFunc(config);
|
||||
VulkanRenderPassStateSerializer passSer(renderPassInfo, key);
|
||||
mRenderPassToKey[renderPass] = key;
|
||||
|
||||
mRenderPassCache[config] = {renderPass, mCurrentTime};
|
||||
|
||||
#if FVK_ENABLED(FVK_DEBUG_FBO_CACHE)
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <backend/TargetBufferInfo.h>
|
||||
|
||||
#include <tsl/robin_map.h>
|
||||
#include <map>
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
@@ -97,6 +98,8 @@ public:
|
||||
explicit VulkanFboCache(VkDevice device);
|
||||
~VulkanFboCache();
|
||||
|
||||
uint32_t getRenderPassKey(VkRenderPass pass) noexcept;
|
||||
|
||||
// Retrieves or creates a VkFramebuffer handle.
|
||||
VkFramebuffer getFramebuffer(FboKey const& config) noexcept;
|
||||
|
||||
@@ -118,6 +121,7 @@ private:
|
||||
FboMap mFramebufferCache;
|
||||
|
||||
tsl::robin_map<RenderPassKey, RenderPassVal, RenderPassHash, RenderPassEq> mRenderPassCache;
|
||||
std::map<VkRenderPass, uint32_t> mRenderPassToKey;
|
||||
tsl::robin_map<VkRenderPass, uint32_t> mRenderPassRefCount;
|
||||
uint32_t mCurrentTime = 0;
|
||||
};
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include <utils/compiler.h> // UTILS_FALLTHROUGH
|
||||
#include <utils/Panic.h> // ASSERT_POSTCONDITION
|
||||
#include <utils/CString.h>
|
||||
#include <fstream>
|
||||
|
||||
using namespace bluevk;
|
||||
|
||||
@@ -179,6 +180,23 @@ VulkanAttachment createSwapchainAttachment(const fvkmemory::resource_ptr<VulkanT
|
||||
};
|
||||
}
|
||||
|
||||
static inline uint64_t serializeShaderModule(utils::CString progName, VkShaderModuleCreateInfo info,
|
||||
VkShaderStageFlagBits stage) {
|
||||
std::stringstream filename;
|
||||
filename << progName.c_str() << "_" << stage << "_";
|
||||
constexpr uint32_t wordReadCount = 8;
|
||||
uint64_t key = utils::hash::murmur3(info.pCode, wordReadCount, 0);
|
||||
key |= uint64_t(utils::hash::murmur3(info.pCode + (wordReadCount / 2), wordReadCount, 0)) << 32;
|
||||
filename << key << ".bin";
|
||||
|
||||
std::ofstream file(filename.str());
|
||||
if (file.is_open()) {
|
||||
file.write(reinterpret_cast<const char*>(info.pCode), info.codeSize);
|
||||
}
|
||||
file.close();
|
||||
return key;
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
VulkanDescriptorSetLayout::VulkanDescriptorSetLayout(DescriptorSetLayout&& layout,
|
||||
@@ -280,6 +298,12 @@ VulkanProgram::VulkanProgram(VkDevice device, Program const& builder) noexcept
|
||||
.codeSize = dataSize,
|
||||
.pCode = data,
|
||||
};
|
||||
if (i == 0) {
|
||||
mVertexShaderHash = serializeShaderModule(name, moduleInfo, VK_SHADER_STAGE_VERTEX_BIT);
|
||||
} else if (i == 1) {
|
||||
mFragmentShaderHash =
|
||||
serializeShaderModule(name, moduleInfo, VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||
}
|
||||
VkResult result = vkCreateShaderModule(mDevice, &moduleInfo, VKALLOC, &module);
|
||||
FILAMENT_CHECK_POSTCONDITION(result == VK_SUCCESS)
|
||||
<< "Unable to create shader module."
|
||||
|
||||
@@ -65,6 +65,8 @@ struct VulkanDescriptorSetLayout : public HwDescriptorSetLayout, fvkmemory::Reso
|
||||
|
||||
using DescriptorSetLayoutArray = std::array<VkDescriptorSetLayout,
|
||||
VulkanDescriptorSetLayout::UNIQUE_DESCRIPTOR_SET_COUNT>;
|
||||
using DescriptorSetLayoutHashArray = std::array<uint64_t,
|
||||
VulkanDescriptorSetLayout::UNIQUE_DESCRIPTOR_SET_COUNT>;
|
||||
|
||||
// The bitmask representation of a set layout.
|
||||
struct Bitmask {
|
||||
@@ -280,6 +282,10 @@ struct VulkanProgram : public HwProgram, fvkmemory::Resource {
|
||||
mInfo->pushConstantDescription.write(cmdbuf, layout, stage, index, value);
|
||||
}
|
||||
|
||||
inline uint64_t getVertexShaderHash() { return mVertexShaderHash;
|
||||
}
|
||||
inline uint64_t getFragmentShaderHash() { return mFragmentShaderHash; }
|
||||
|
||||
// TODO: handle compute shaders.
|
||||
// The expected order of shaders - from frontend to backend - is vertex, fragment, compute.
|
||||
static constexpr uint8_t const MAX_SHADER_MODULES = 2;
|
||||
@@ -295,6 +301,8 @@ private:
|
||||
};
|
||||
|
||||
PipelineInfo* mInfo;
|
||||
uint64_t mVertexShaderHash;
|
||||
uint64_t mFragmentShaderHash;
|
||||
VkDevice mDevice = VK_NULL_HANDLE;
|
||||
};
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
|
||||
#include "VulkanPipelineCache.h"
|
||||
#include "VulkanPipelineStateSerializer.h"
|
||||
|
||||
#include <utils/Log.h>
|
||||
#include <utils/Panic.h>
|
||||
@@ -42,8 +43,9 @@ VulkanPipelineCache::VulkanPipelineCache(VkDevice device)
|
||||
bluevk::vkCreatePipelineCache(mDevice, &createInfo, VKALLOC, &mPipelineCache);
|
||||
}
|
||||
|
||||
void VulkanPipelineCache::bindLayout(VkPipelineLayout layout) noexcept {
|
||||
void VulkanPipelineCache::bindLayout(VkPipelineLayout layout, uint32_t key) noexcept {
|
||||
mPipelineRequirements.layout = layout;
|
||||
mPipelineLayoutKey = key;
|
||||
}
|
||||
|
||||
VulkanPipelineCache::PipelineCacheEntry* VulkanPipelineCache::getOrCreatePipeline() noexcept {
|
||||
@@ -77,6 +79,7 @@ void VulkanPipelineCache::bindPipeline(VulkanCommandBuffer* commands) {
|
||||
VulkanPipelineCache::PipelineCacheEntry* VulkanPipelineCache::createPipeline() noexcept {
|
||||
assert_invariant(mPipelineRequirements.shaders[0] && "Vertex shader is not bound.");
|
||||
assert_invariant(mPipelineRequirements.layout && "No pipeline layout specified");
|
||||
VulkanPipelineStateSerializer serializer(mProgramName);
|
||||
|
||||
VkPipelineShaderStageCreateInfo shaderStages[SHADER_MODULE_COUNT];
|
||||
shaderStages[0] = {
|
||||
@@ -89,6 +92,12 @@ VulkanPipelineCache::PipelineCacheEntry* VulkanPipelineCache::createPipeline() n
|
||||
shaderStages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||
shaderStages[1].module = mPipelineRequirements.shaders[1];
|
||||
|
||||
VulkanPipelineStateSerializer::ShaderStageInfo vtx = { shaderStages[0].stage, mVertexShaderHash,
|
||||
shaderStages[0].pName };
|
||||
VulkanPipelineStateSerializer::ShaderStageInfo frg = { shaderStages[1].stage, mFragmentShaderHash,
|
||||
shaderStages[1].pName };
|
||||
serializer << vtx << frg;
|
||||
|
||||
bool const hasFragmentShader = shaderStages[1].module != VK_NULL_HANDLE;
|
||||
|
||||
VkPipelineColorBlendAttachmentState colorBlendAttachments[MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT];
|
||||
@@ -107,9 +116,11 @@ VulkanPipelineCache::PipelineCacheEntry* VulkanPipelineCache::createPipeline() n
|
||||
for (uint32_t i = 0; i < VERTEX_ATTRIBUTE_COUNT; i++) {
|
||||
if (mPipelineRequirements.vertexAttributes[i].format > 0) {
|
||||
vertexAttributes[numVertexAttribs++] = mPipelineRequirements.vertexAttributes[i];
|
||||
serializer << mPipelineRequirements.vertexAttributes[i];
|
||||
}
|
||||
if (mPipelineRequirements.vertexBuffers[i].stride > 0) {
|
||||
vertexBuffers[numVertexBuffers++] = mPipelineRequirements.vertexBuffers[i];
|
||||
serializer << mPipelineRequirements.vertexBuffers[i];
|
||||
}
|
||||
}
|
||||
VkPipelineVertexInputStateCreateInfo vertexInputState = {
|
||||
@@ -123,11 +134,15 @@ VulkanPipelineCache::PipelineCacheEntry* VulkanPipelineCache::createPipeline() n
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
|
||||
.topology = (VkPrimitiveTopology) mPipelineRequirements.topology,
|
||||
};
|
||||
serializer << inputAssemblyState;
|
||||
|
||||
VkPipelineViewportStateCreateInfo viewportState = {
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
|
||||
.viewportCount = 1,
|
||||
.scissorCount = 1,
|
||||
};
|
||||
serializer << viewportState;
|
||||
|
||||
VkDynamicState dynamicStateEnables[] = {
|
||||
VK_DYNAMIC_STATE_VIEWPORT,
|
||||
VK_DYNAMIC_STATE_SCISSOR,
|
||||
@@ -137,6 +152,8 @@ VulkanPipelineCache::PipelineCacheEntry* VulkanPipelineCache::createPipeline() n
|
||||
.dynamicStateCount = 2,
|
||||
.pDynamicStates = dynamicStateEnables,
|
||||
};
|
||||
serializer << dynamicState;
|
||||
|
||||
auto const& raster = mPipelineRequirements.rasterState;
|
||||
VkPipelineRasterizationStateCreateInfo vkRaster = {
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
|
||||
@@ -150,6 +167,8 @@ VulkanPipelineCache::PipelineCacheEntry* VulkanPipelineCache::createPipeline() n
|
||||
.depthBiasSlopeFactor = raster.depthBiasSlopeFactor,
|
||||
.lineWidth = 1.0f,
|
||||
};
|
||||
serializer << vkRaster;
|
||||
|
||||
VkPipelineMultisampleStateCreateInfo vkMs = {
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
|
||||
.rasterizationSamples = (VkSampleCountFlagBits) raster.rasterizationSamples,
|
||||
@@ -158,6 +177,8 @@ VulkanPipelineCache::PipelineCacheEntry* VulkanPipelineCache::createPipeline() n
|
||||
.alphaToCoverageEnable = raster.alphaToCoverageEnable,
|
||||
.alphaToOneEnable = VK_FALSE,
|
||||
};
|
||||
serializer << vkMs;
|
||||
|
||||
VkPipelineDepthStencilStateCreateInfo vkDs = {
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
|
||||
.depthTestEnable = VK_TRUE,
|
||||
@@ -177,6 +198,12 @@ VulkanPipelineCache::PipelineCacheEntry* VulkanPipelineCache::createPipeline() n
|
||||
.writeMask = 0u,
|
||||
.reference = 0u,
|
||||
};
|
||||
serializer << vkDs;
|
||||
|
||||
//layout
|
||||
serializer.setPipelineLayoutKey(mPipelineLayoutKey);
|
||||
// renderPass
|
||||
serializer.setRenderPassKey(mRenderPassKey);
|
||||
|
||||
VkGraphicsPipelineCreateInfo pipelineCreateInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
|
||||
@@ -215,6 +242,7 @@ VulkanPipelineCache::PipelineCacheEntry* VulkanPipelineCache::createPipeline() n
|
||||
colorBlendAttachments[i] = colorBlendAttachments[0];
|
||||
}
|
||||
}
|
||||
serializer << colorBlendState;
|
||||
|
||||
#if FVK_ENABLED(FVK_DEBUG_SHADER_MODULE)
|
||||
FVK_LOGD << "vkCreateGraphicsPipelines with shaders = ("
|
||||
@@ -230,12 +258,20 @@ VulkanPipelineCache::PipelineCacheEntry* VulkanPipelineCache::createPipeline() n
|
||||
FVK_LOGE << "vkCreateGraphicsPipelines error " << error;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
PipelineHashFn hashFunc;
|
||||
|
||||
serializer.setID(hashFunc(mPipelineRequirements));
|
||||
return &mPipelines.emplace(mPipelineRequirements, cacheEntry).first.value();
|
||||
}
|
||||
|
||||
void VulkanPipelineCache::bindProgram(fvkmemory::resource_ptr<VulkanProgram> program) noexcept {
|
||||
mPipelineRequirements.shaders[0] = program->getVertexShader();
|
||||
mPipelineRequirements.shaders[1] = program->getFragmentShader();
|
||||
mProgramName = program->name;
|
||||
mVertexShaderHash = program->getVertexShaderHash();
|
||||
mFragmentShaderHash= program->getFragmentShaderHash();
|
||||
|
||||
|
||||
// If this is a debug build, validate the current shader.
|
||||
#if FVK_ENABLED(FVK_DEBUG_SHADER_MODULE)
|
||||
@@ -250,9 +286,10 @@ void VulkanPipelineCache::bindRasterState(RasterState const& rasterState) noexce
|
||||
mPipelineRequirements.rasterState = rasterState;
|
||||
}
|
||||
|
||||
void VulkanPipelineCache::bindRenderPass(VkRenderPass renderPass, int subpassIndex) noexcept {
|
||||
void VulkanPipelineCache::bindRenderPass(VkRenderPass renderPass, uint32_t passKey, int subpassIndex) noexcept {
|
||||
mPipelineRequirements.renderPass = renderPass;
|
||||
mPipelineRequirements.subpassIndex = subpassIndex;
|
||||
mRenderPassKey = passKey;
|
||||
}
|
||||
|
||||
void VulkanPipelineCache::bindPrimitiveTopology(VkPrimitiveTopology topology) noexcept {
|
||||
|
||||
@@ -88,7 +88,7 @@ public:
|
||||
|
||||
VulkanPipelineCache(VkDevice device);
|
||||
|
||||
void bindLayout(VkPipelineLayout layout) noexcept;
|
||||
void bindLayout(VkPipelineLayout layout, uint32_t key) noexcept;
|
||||
|
||||
// Creates a new pipeline if necessary and binds it using vkCmdBindPipeline.
|
||||
void bindPipeline(VulkanCommandBuffer* commands);
|
||||
@@ -96,7 +96,7 @@ public:
|
||||
// Each of the following methods are fast and do not make Vulkan calls.
|
||||
void bindProgram(fvkmemory::resource_ptr<VulkanProgram> program) noexcept;
|
||||
void bindRasterState(RasterState const& rasterState) noexcept;
|
||||
void bindRenderPass(VkRenderPass renderPass, int subpassIndex) noexcept;
|
||||
void bindRenderPass(VkRenderPass renderPass, uint32_t passKey, int subpassIndex) noexcept;
|
||||
void bindPrimitiveTopology(VkPrimitiveTopology topology) noexcept;
|
||||
void bindVertexArray(VkVertexInputAttributeDescription const* attribDesc,
|
||||
VkVertexInputBindingDescription const* bufferDesc, uint8_t count);
|
||||
@@ -207,6 +207,11 @@ private:
|
||||
|
||||
// Current requirements for the pipeline layout, pipeline, and descriptor sets.
|
||||
PipelineKey mPipelineRequirements = {};
|
||||
utils::CString mProgramName;
|
||||
uint64_t mVertexShaderHash;
|
||||
uint64_t mFragmentShaderHash;
|
||||
uint32_t mPipelineLayoutKey;
|
||||
uint32_t mRenderPassKey;
|
||||
|
||||
// Current bindings for the pipeline and descriptor sets.
|
||||
PipelineKey mBoundPipeline = {};
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
|
||||
#include "VulkanPipelineLayoutCache.h"
|
||||
#include "VulkanDescriptorSetLayoutSerializer.h"
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
@@ -23,7 +24,11 @@ VkPipelineLayout VulkanPipelineLayoutCache::getLayout(
|
||||
fvkmemory::resource_ptr<VulkanProgram> program) {
|
||||
PipelineLayoutKey key = {};
|
||||
uint8_t descSetLayoutCount = 0;
|
||||
key.descSetLayouts = descriptorSetLayouts;
|
||||
DescriptorSetLayoutHashArray hashArray;
|
||||
for (uint32_t i = 0; i < descriptorSetLayouts.size(); ++i) {
|
||||
hashArray[i] = mDescriptorSetCache->getKey(descriptorSetLayouts[i]);
|
||||
}
|
||||
key.descSetLayouts = hashArray;
|
||||
for (auto layoutHandle: descriptorSetLayouts) {
|
||||
if (layoutHandle == VK_NULL_HANDLE) {
|
||||
break;
|
||||
@@ -62,11 +67,14 @@ VkPipelineLayout VulkanPipelineLayoutCache::getLayout(
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
|
||||
.pNext = nullptr,
|
||||
.setLayoutCount = (uint32_t) descSetLayoutCount,
|
||||
.pSetLayouts = key.descSetLayouts.data(),
|
||||
.pSetLayouts = descriptorSetLayouts.data(),
|
||||
.pushConstantRangeCount = pushConstantRangeCount,
|
||||
.pPushConstantRanges = pushConstantRanges,
|
||||
};
|
||||
|
||||
PipelineLayoutKeyHashFn hashFunc;
|
||||
uint32_t hashedKey = hashFunc(key);
|
||||
VulkanPipelineLayoutSerializer pipelineSer(info, mDescriptorSetCache, hashedKey);
|
||||
VkPipelineLayout layout;
|
||||
vkCreatePipelineLayout(mDevice, &info, VKALLOC, &layout);
|
||||
|
||||
@@ -74,6 +82,8 @@ VkPipelineLayout VulkanPipelineLayoutCache::getLayout(
|
||||
.handle = layout,
|
||||
.lastUsed = mTimestamp++,
|
||||
};
|
||||
|
||||
mPipelineToKey[layout] = hashedKey;
|
||||
return layout;
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#define TNT_FILAMENT_BACKEND_VULKANPIPELINELAYOUTCACHE_H
|
||||
|
||||
#include "VulkanHandles.h"
|
||||
#include "VulkanDescriptorSetLayoutCache.h"
|
||||
|
||||
#include <bluevk/BlueVK.h>
|
||||
|
||||
@@ -30,10 +31,11 @@ namespace filament::backend {
|
||||
class VulkanPipelineLayoutCache {
|
||||
public:
|
||||
using DescriptorSetLayoutArray = VulkanDescriptorSetLayout::DescriptorSetLayoutArray;
|
||||
using DescriptorSetLayoutHashArray = VulkanDescriptorSetLayout::DescriptorSetLayoutHashArray;
|
||||
|
||||
VulkanPipelineLayoutCache(VkDevice device)
|
||||
VulkanPipelineLayoutCache(VkDevice device, VulkanDescriptorSetLayoutCache* cache)
|
||||
: mDevice(device),
|
||||
mTimestamp(0) {}
|
||||
mTimestamp(0), mDescriptorSetCache(cache) {}
|
||||
|
||||
void terminate() noexcept;
|
||||
|
||||
@@ -45,7 +47,7 @@ public:
|
||||
};
|
||||
|
||||
struct PipelineLayoutKey {
|
||||
DescriptorSetLayoutArray descSetLayouts = {}; // 8 * 4
|
||||
DescriptorSetLayoutHashArray descSetLayouts = {}; // 8 * 4
|
||||
PushConstantKey pushConstant[Program::SHADER_TYPE_COUNT] = {}; // 2 * 3
|
||||
uint16_t padding = 0;
|
||||
};
|
||||
@@ -58,6 +60,14 @@ public:
|
||||
// are described in the program.
|
||||
VkPipelineLayout getLayout(DescriptorSetLayoutArray const& descriptorSetLayouts,
|
||||
fvkmemory::resource_ptr<VulkanProgram> program);
|
||||
uint32_t getKey(VkPipelineLayout layout) {
|
||||
uint32_t key = 0;
|
||||
auto iter = mPipelineToKey.find(layout);
|
||||
if (iter != mPipelineToKey.end()) {
|
||||
key = iter->second;
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
private:
|
||||
using Timestamp = uint64_t;
|
||||
@@ -79,6 +89,8 @@ private:
|
||||
VkDevice mDevice;
|
||||
Timestamp mTimestamp;
|
||||
PipelineLayoutMap mPipelineLayouts;
|
||||
std::map<VkPipelineLayout, uint32_t> mPipelineToKey;
|
||||
VulkanDescriptorSetLayoutCache* mDescriptorSetCache;
|
||||
};
|
||||
|
||||
} // filament::backend
|
||||
|
||||
251
filament/backend/src/vulkan/VulkanPipelineStateSerializer.cpp
Normal file
251
filament/backend/src/vulkan/VulkanPipelineStateSerializer.cpp
Normal file
@@ -0,0 +1,251 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <fstream>
|
||||
|
||||
#include "VulkanPipelineStateSerializer.h"
|
||||
#include <utils/Log.h>
|
||||
#include <utils/Panic.h>
|
||||
|
||||
#include "VulkanConstants.h"
|
||||
#include "VulkanHandles.h"
|
||||
|
||||
#if defined(__clang__)
|
||||
// Vulkan functions often immediately dereference pointers, so it's fine to pass in a pointer
|
||||
// to a stack-allocated variable.
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wreturn-stack-address"
|
||||
#endif
|
||||
|
||||
using namespace bluevk;
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
VulkanPipelineStateSerializer::VulkanPipelineStateSerializer(const utils::CString& name) {
|
||||
mBuffer << "{" << std::endl;
|
||||
mBuffer << "\"program_name\":" << "\"" << name.c_str() << "\"" << "," << std::endl;
|
||||
}
|
||||
VulkanPipelineStateSerializer::~VulkanPipelineStateSerializer() {
|
||||
//Shader Modules
|
||||
mBuffer << "\"shader_modules\":[" << std::endl;
|
||||
for (uint32_t i = 0; i < mShaderStages.size(); ++i) {
|
||||
mBuffer << "{" << std::endl;
|
||||
mBuffer << "\"stage\":" << mShaderStages[i].stage << "," << std::endl;
|
||||
mBuffer << "\"key\":" << mShaderStages[i].module << "," << std::endl;
|
||||
mBuffer << "\"name\":" << "\"" << mShaderStages[i].mName << "\"" << std::endl;
|
||||
mBuffer << "}";
|
||||
if (i < mShaderStages.size() - 1) {
|
||||
mBuffer << ",";
|
||||
}
|
||||
mBuffer << std::endl;
|
||||
}
|
||||
mBuffer << "]," << std::endl;
|
||||
|
||||
//Vertex Attribute
|
||||
mBuffer << "\"vertex_attributes\":[" << std::endl;
|
||||
for (uint32_t i = 0; i < mVtxAttribs.size(); ++i) {
|
||||
mBuffer << "{" << std::endl;
|
||||
mBuffer << "\"location\":" << mVtxAttribs[i].location << "," << std::endl;
|
||||
mBuffer << "\"binding\":" << mVtxAttribs[i].binding << "," << std::endl;
|
||||
mBuffer << "\"format\":" << mVtxAttribs[i].format << "," << std::endl;
|
||||
mBuffer << "\"offset\":" << mVtxAttribs[i].offset << std::endl;
|
||||
mBuffer << "}";
|
||||
if (i < mVtxAttribs.size() - 1) {
|
||||
mBuffer << ",";
|
||||
}
|
||||
mBuffer << std::endl;
|
||||
}
|
||||
mBuffer << "]," << std::endl;
|
||||
|
||||
// Vertex Bindings
|
||||
mBuffer << "\"vertex_bindings\":[" << std::endl;
|
||||
for (uint32_t i = 0; i < mVtxBindings.size(); ++i) {
|
||||
mBuffer << "{" << std::endl;
|
||||
mBuffer << "\"binding\":" << mVtxBindings[i].binding << "," << std::endl;
|
||||
mBuffer << "\"stride\":" << mVtxBindings[i].stride << "," << std::endl;
|
||||
mBuffer << "\"input_rate\":" << mVtxBindings[i].inputRate << std::endl;
|
||||
mBuffer << "}";
|
||||
if (i < mVtxBindings.size() - 1) {
|
||||
mBuffer << ",";
|
||||
}
|
||||
mBuffer << std::endl;
|
||||
}
|
||||
mBuffer << "]" << std::endl;
|
||||
|
||||
mBuffer << "}" << std::endl;
|
||||
|
||||
std::ofstream file(mFileName);
|
||||
if (file.is_open()) {
|
||||
file << mBuffer.str();
|
||||
}
|
||||
file.close();
|
||||
}
|
||||
|
||||
void VulkanPipelineStateSerializer::setPipelineLayoutKey(uint32_t pipelineLayoutKey) {
|
||||
mBuffer << "\"layout\":" << pipelineLayoutKey << "," << std::endl;
|
||||
}
|
||||
|
||||
void VulkanPipelineStateSerializer::setRenderPassKey(uint32_t renderPassKey) {
|
||||
mBuffer << "\"render_pass\":" << renderPassKey << "," << std::endl;
|
||||
}
|
||||
|
||||
void VulkanPipelineStateSerializer::setID(uint32_t key) {
|
||||
std::stringstream temp;
|
||||
temp << "pipeline_" << key << ".json";
|
||||
temp >> mFileName;
|
||||
}
|
||||
|
||||
VulkanPipelineStateSerializer& VulkanPipelineStateSerializer::operator<<(
|
||||
const VkPipelineInputAssemblyStateCreateInfo& inputAsm) {
|
||||
mBuffer << "\"topology\":" << inputAsm.topology << "," << std::endl;
|
||||
return *this;
|
||||
}
|
||||
|
||||
VulkanPipelineStateSerializer& VulkanPipelineStateSerializer::operator<<(
|
||||
const VkPipelineViewportStateCreateInfo& viewport) {
|
||||
mBuffer << "\"viewport_count\":" << viewport.viewportCount << "," << std::endl;
|
||||
mBuffer << "\"scissor_count\":" << viewport.scissorCount << "," << std::endl;
|
||||
return *this;
|
||||
}
|
||||
|
||||
VulkanPipelineStateSerializer& VulkanPipelineStateSerializer::operator<<(
|
||||
const VkPipelineRasterizationStateCreateInfo& rasterState) {
|
||||
mBuffer << "\"raster_states\":{" << std::endl;
|
||||
mBuffer << "\"depth_clamp_enable\":" << rasterState.depthClampEnable << "," << std::endl;
|
||||
mBuffer << "\"polygon_mode\":" << rasterState.polygonMode << "," << std::endl;
|
||||
mBuffer << "\"cull_mode\":" << rasterState.cullMode << "," << std::endl;
|
||||
mBuffer << "\"front_face\":" << rasterState.frontFace << "," << std::endl;
|
||||
mBuffer << "\"depth_bias_enable\":" << rasterState.depthBiasEnable << "," << std::endl;
|
||||
mBuffer << "\"depth_bias_constant_factor\":" << rasterState.depthBiasConstantFactor << ","
|
||||
<< std::endl;
|
||||
mBuffer << "\"depth_bias_clamp\":" << rasterState.depthBiasClamp << "," << std::endl;
|
||||
mBuffer << "\"depth_bias_slope_factor\":" << rasterState.depthBiasSlopeFactor << "," << std::endl;
|
||||
mBuffer << "\"line_width\":" << rasterState.lineWidth << std::endl;
|
||||
mBuffer << "}," << std::endl;
|
||||
return *this;
|
||||
}
|
||||
|
||||
VulkanPipelineStateSerializer& VulkanPipelineStateSerializer::operator<<(
|
||||
const VkPipelineDepthStencilStateCreateInfo& depthStencil) {
|
||||
mBuffer << "\"depth_stencil_states\":{" << std::endl;
|
||||
mBuffer << "\"depth_test_enable\":" << depthStencil.depthTestEnable << "," << std::endl;
|
||||
mBuffer << "\"depth_write_enable\":" << depthStencil.depthWriteEnable << "," << std::endl;
|
||||
mBuffer << "\"depth_compare_op\":" << depthStencil.depthCompareOp << "," << std::endl;
|
||||
mBuffer << "\"depth_bounds_test_enable\":" << depthStencil.depthBoundsTestEnable << ","
|
||||
<< std::endl;
|
||||
mBuffer << "\"min_depth_bounds\":" << depthStencil.minDepthBounds << "," << std::endl;
|
||||
mBuffer << "\"max_depth_bounds\":" << depthStencil.maxDepthBounds << "," << std::endl;
|
||||
mBuffer << "\"front\":{" << std::endl;
|
||||
mBuffer << "\"fail_op\":" << depthStencil.front.failOp << "," << std::endl;
|
||||
mBuffer << "\"pass_op\":" << depthStencil.front.passOp << "," << std::endl;
|
||||
mBuffer << "\"depth_fail_op\":" << depthStencil.front.depthFailOp << "," << std::endl;
|
||||
mBuffer << "\"compare_op\":" << depthStencil.front.compareOp << "," << std::endl;
|
||||
mBuffer << "\"compare_mask\":" << depthStencil.front.compareMask << "," << std::endl;
|
||||
mBuffer << "\"write_mask\":" << depthStencil.front.writeMask << "," << std::endl;
|
||||
mBuffer << "\"reference\":" << depthStencil.front.reference << std::endl;
|
||||
mBuffer << "}," << std::endl;
|
||||
mBuffer << "\"back\":{" << std::endl;
|
||||
mBuffer << "\"fail_op\":" << depthStencil.back.failOp << "," << std::endl;
|
||||
mBuffer << "\"pass_op\":" << depthStencil.back.passOp << "," << std::endl;
|
||||
mBuffer << "\"depth_fail_op\":" << depthStencil.back.depthFailOp << "," << std::endl;
|
||||
mBuffer << "\"compare_op\":" << depthStencil.back.compareOp << "," << std::endl;
|
||||
mBuffer << "\"compare_mask\":" << depthStencil.back.compareMask << "," << std::endl;
|
||||
mBuffer << "\"write_mask\":" << depthStencil.back.writeMask << "," << std::endl;
|
||||
mBuffer << "\"reference\":" << depthStencil.back.reference << std::endl;
|
||||
mBuffer << "}" << std::endl;
|
||||
mBuffer << "}," << std::endl;
|
||||
return *this;
|
||||
}
|
||||
|
||||
VulkanPipelineStateSerializer& VulkanPipelineStateSerializer::operator<<(
|
||||
const VkPipelineMultisampleStateCreateInfo& multiSample) {
|
||||
mBuffer << "\"multisample_states\":{" << std::endl;
|
||||
mBuffer << "\"rasterization_samples\":" << multiSample.rasterizationSamples << "," << std::endl;
|
||||
mBuffer << "\"sample_shading_enable\":" << multiSample.sampleShadingEnable << "," << std::endl;
|
||||
mBuffer << "\"min_sample_shading\":" << multiSample.minSampleShading << "," << std::endl;
|
||||
mBuffer << "\"alpha_to_coverage_enable\":" << multiSample.alphaToCoverageEnable << ","
|
||||
<< std::endl;
|
||||
mBuffer << "\"alpha_to_one_enable\":" << multiSample.alphaToOneEnable << std::endl;
|
||||
mBuffer << "}," << std::endl;
|
||||
return *this;
|
||||
}
|
||||
|
||||
VulkanPipelineStateSerializer& VulkanPipelineStateSerializer::operator<<(
|
||||
const VkPipelineDynamicStateCreateInfo& dyStates) {
|
||||
mBuffer << "\"dynamic_states\":[" << std::endl;
|
||||
for (uint32_t i = 0; i < dyStates.dynamicStateCount; ++i) {
|
||||
mBuffer << dyStates.pDynamicStates[i];
|
||||
if (i < dyStates.dynamicStateCount - 1) {
|
||||
mBuffer << ",";
|
||||
}
|
||||
mBuffer << std::endl;
|
||||
}
|
||||
mBuffer << "]," << std::endl;
|
||||
return *this;
|
||||
}
|
||||
|
||||
VulkanPipelineStateSerializer& VulkanPipelineStateSerializer::operator<<(
|
||||
const VkPipelineColorBlendStateCreateInfo& blendStateInfo) {
|
||||
mBuffer << "\"color_blend_state_attachments\":[" << std::endl;
|
||||
for (uint32_t i = 0; i < blendStateInfo.attachmentCount; ++i) {
|
||||
mBuffer << "{" << std::endl;
|
||||
mBuffer << "\"blend_enable\":" << blendStateInfo.pAttachments[i].blendEnable << ","
|
||||
<< std::endl;
|
||||
mBuffer << "\"src_color_blend_factor\":" << blendStateInfo.pAttachments[i].srcColorBlendFactor
|
||||
<< ","
|
||||
<< std::endl;
|
||||
mBuffer << "\"dst_color_blend_factor\":" << blendStateInfo.pAttachments[i].dstColorBlendFactor
|
||||
<< ","
|
||||
<< std::endl;
|
||||
mBuffer << "\"color_blend_op\":" << blendStateInfo.pAttachments[i].colorBlendOp << ","
|
||||
<< std::endl;
|
||||
mBuffer << "\"src_alpha_blend_factor\":" << blendStateInfo.pAttachments[i].srcAlphaBlendFactor
|
||||
<< ","
|
||||
<< std::endl;
|
||||
mBuffer << "\"dst_alpha_blend_factor\":" << blendStateInfo.pAttachments[i].dstAlphaBlendFactor
|
||||
<< ","
|
||||
<< std::endl;
|
||||
mBuffer << "\"alpha_blend_op\":" << blendStateInfo.pAttachments[i].alphaBlendOp << ","
|
||||
<< std::endl;
|
||||
mBuffer << "\"color_write_mask\":" << blendStateInfo.pAttachments[i].colorWriteMask
|
||||
<< std::endl;
|
||||
mBuffer << "}";
|
||||
if (i < blendStateInfo.attachmentCount - 1) {
|
||||
mBuffer << ",";
|
||||
}
|
||||
mBuffer << std::endl;
|
||||
}
|
||||
mBuffer << "]," << std::endl;
|
||||
return *this;
|
||||
}
|
||||
|
||||
VulkanPipelineStateSerializer& VulkanPipelineStateSerializer::operator<<(
|
||||
const ShaderStageInfo& shaderStages) {
|
||||
mShaderStages.push_back(shaderStages);
|
||||
return *this;
|
||||
}
|
||||
|
||||
VulkanPipelineStateSerializer& VulkanPipelineStateSerializer::operator<<(
|
||||
const VkVertexInputAttributeDescription& attrib) {
|
||||
mVtxAttribs.push_back(attrib);
|
||||
return *this;
|
||||
}
|
||||
VulkanPipelineStateSerializer& VulkanPipelineStateSerializer::operator<<(
|
||||
const VkVertexInputBindingDescription& binding) {
|
||||
mVtxBindings.push_back(binding);
|
||||
return *this;
|
||||
}
|
||||
}
|
||||
79
filament/backend/src/vulkan/VulkanPipelineStateSerializer.h
Normal file
79
filament/backend/src/vulkan/VulkanPipelineStateSerializer.h
Normal file
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef TNT_FILAMENT_BACKEND_VULKANPIPELINESTATESERIALIZER_H
|
||||
#define TNT_FILAMENT_BACKEND_VULKANPIPELINESTATESERIALIZER_H
|
||||
|
||||
#include "VulkanCommands.h"
|
||||
|
||||
#include <backend/DriverEnums.h>
|
||||
#include <backend/TargetBufferInfo.h>
|
||||
|
||||
#include <bluevk/BlueVK.h>
|
||||
#include <iostream>
|
||||
#include <type_traits>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
// VulkanPipelineStateSerializer stores to a file the pipeline states.
|
||||
class VulkanPipelineStateSerializer {
|
||||
public:
|
||||
VulkanPipelineStateSerializer(VulkanPipelineStateSerializer const&) = delete;
|
||||
VulkanPipelineStateSerializer& operator=(VulkanPipelineStateSerializer const&) = delete;
|
||||
|
||||
VulkanPipelineStateSerializer(const utils::CString& name);
|
||||
~VulkanPipelineStateSerializer();
|
||||
|
||||
void setID(uint32_t key);
|
||||
void setPipelineLayoutKey(uint32_t pipelineLayoutKey);
|
||||
void setRenderPassKey(uint32_t renderPassKey);
|
||||
VulkanPipelineStateSerializer& operator<<(
|
||||
const VkPipelineInputAssemblyStateCreateInfo& inputAsm);
|
||||
VulkanPipelineStateSerializer& operator<<(const VkPipelineViewportStateCreateInfo& viewport);
|
||||
VulkanPipelineStateSerializer& operator<<(const VkPipelineDynamicStateCreateInfo& dyStates);
|
||||
VulkanPipelineStateSerializer& operator<<(
|
||||
const VkPipelineRasterizationStateCreateInfo& rasterState);
|
||||
VulkanPipelineStateSerializer& operator<<(
|
||||
const VkPipelineDepthStencilStateCreateInfo& depthStencil);
|
||||
VulkanPipelineStateSerializer& operator<<(const VkPipelineMultisampleStateCreateInfo& multiSample);
|
||||
VulkanPipelineStateSerializer& operator<<(
|
||||
const VkPipelineColorBlendStateCreateInfo& blendStateInfo);
|
||||
|
||||
struct ShaderStageInfo {
|
||||
VkShaderStageFlagBits stage;
|
||||
uint64_t module;
|
||||
std::string mName;
|
||||
};
|
||||
VulkanPipelineStateSerializer& operator<<(const ShaderStageInfo& shaderStages);
|
||||
VulkanPipelineStateSerializer& operator<<(
|
||||
const VkVertexInputAttributeDescription& attrib);
|
||||
VulkanPipelineStateSerializer& operator<<(const VkVertexInputBindingDescription& binding);
|
||||
|
||||
private:
|
||||
std::string mFileName;
|
||||
std::stringstream mBuffer;
|
||||
|
||||
//temp data
|
||||
utils::CString mProgramName;
|
||||
std::vector<ShaderStageInfo> mShaderStages;
|
||||
std::vector<VkVertexInputAttributeDescription> mVtxAttribs;
|
||||
std::vector<VkVertexInputBindingDescription> mVtxBindings;
|
||||
};
|
||||
} // namespace filament::backend
|
||||
|
||||
#endif //TNT_FILAMENT_BACKEND_VULKANPIPELINESTATESERIALIZER_H
|
||||
157
filament/backend/src/vulkan/VulkanRenderPassStateSerializer.cpp
Normal file
157
filament/backend/src/vulkan/VulkanRenderPassStateSerializer.cpp
Normal file
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <fstream>
|
||||
|
||||
#include "VulkanRenderPassStateSerializer.h"
|
||||
#include <utils/Log.h>
|
||||
#include <utils/Panic.h>
|
||||
|
||||
#include "VulkanConstants.h"
|
||||
#include "VulkanHandles.h"
|
||||
|
||||
#if defined(__clang__)
|
||||
// Vulkan functions often immediately dereference pointers, so it's fine to pass in a pointer
|
||||
// to a stack-allocated variable.
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wreturn-stack-address"
|
||||
#endif
|
||||
|
||||
using namespace bluevk;
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
VulkanRenderPassStateSerializer::VulkanRenderPassStateSerializer(
|
||||
const VkRenderPassCreateInfo& info, uint32_t key) {
|
||||
std::stringstream filename;
|
||||
filename << "render_pass_" << key << ".json";
|
||||
|
||||
std::ofstream file(filename.str());
|
||||
if (file.is_open()) {
|
||||
std::stringstream buffer;
|
||||
buffer << "{" << std::endl;
|
||||
buffer << "\"attachments\":[" << std::endl;
|
||||
for (uint32_t i = 0; i < info.attachmentCount; ++i) {
|
||||
buffer << "{" << std::endl;
|
||||
buffer << "\"flags\":" << info.pAttachments[i].flags << "," << std::endl;
|
||||
buffer << "\"format\":" << info.pAttachments[i].format << "," << std::endl;
|
||||
buffer << "\"samples\":" << info.pAttachments[i].samples << "," << std::endl;
|
||||
buffer << "\"load_op\":" << info.pAttachments[i].loadOp << "," << std::endl;
|
||||
buffer << "\"store_op\":" << info.pAttachments[i].storeOp << "," << std::endl;
|
||||
buffer << "\"stencil_load_op\":" << info.pAttachments[i].stencilLoadOp << "," << std::endl;
|
||||
buffer << "\"stencil_store_op\":" << info.pAttachments[i].stencilStoreOp << "," << std::endl;
|
||||
buffer << "\"initial_layout\":" << info.pAttachments[i].initialLayout << "," << std::endl;
|
||||
buffer << "\"final_layout\":" << info.pAttachments[i].finalLayout << std::endl;
|
||||
buffer << "}";
|
||||
if (i < info.attachmentCount - 1) {
|
||||
buffer << ",";
|
||||
}
|
||||
buffer << std::endl;
|
||||
}
|
||||
buffer << "]," << std::endl;
|
||||
|
||||
buffer << "\"subpasses\":[" << std::endl;
|
||||
for (uint32_t i = 0; i < info.subpassCount; ++i) {
|
||||
buffer << "{" << std::endl;
|
||||
buffer << "\"flags\":" << info.pSubpasses[i].flags << "," << std::endl;
|
||||
buffer << "\"pipeline_bind_point\":" << info.pSubpasses[i].pipelineBindPoint;
|
||||
|
||||
//------------depth stencil-------------------
|
||||
if (info.pSubpasses[i].pDepthStencilAttachment) {
|
||||
buffer << "," << std::endl;
|
||||
buffer << "\"depth_stencil_attachment\":{" << std::endl;
|
||||
buffer << "\"attachement\":"
|
||||
<< info.pSubpasses[i].pDepthStencilAttachment->attachment << ","
|
||||
<< std::endl;
|
||||
buffer << "\"layout\":" << info.pSubpasses[i].pDepthStencilAttachment->layout
|
||||
<< std::endl;
|
||||
buffer << "}";
|
||||
}
|
||||
|
||||
//------------Resolve-------------------
|
||||
if (info.pSubpasses[i].pResolveAttachments) {
|
||||
buffer << "," << std::endl;
|
||||
buffer << "\"resolve_attachments\":[" << std::endl;
|
||||
for (uint32_t j = 0; j < info.pSubpasses[i].colorAttachmentCount; ++j) {
|
||||
buffer << "{" << std::endl;
|
||||
buffer << "\"attachement\":"
|
||||
<< info.pSubpasses[i].pResolveAttachments[j].attachment << ","
|
||||
<< std::endl;
|
||||
buffer << "\"layout\":" << info.pSubpasses[i].pResolveAttachments[j].layout
|
||||
<< std::endl;
|
||||
buffer << "}" << std::endl;
|
||||
if (j < info.pSubpasses[i].colorAttachmentCount - 1) {
|
||||
buffer << ",";
|
||||
}
|
||||
buffer << std::endl;
|
||||
}
|
||||
buffer << "]";
|
||||
}
|
||||
|
||||
//------------Color-------------------
|
||||
if (info.pSubpasses[i].pColorAttachments) {
|
||||
buffer << "," << std::endl;
|
||||
buffer << "\"color_attachments\":[" << std::endl;
|
||||
for (uint32_t j = 0; j < info.pSubpasses[i].colorAttachmentCount; ++j) {
|
||||
buffer << "{" << std::endl;
|
||||
buffer << "\"attachement\":"
|
||||
<< info.pSubpasses[i].pColorAttachments[j].attachment << ","
|
||||
<< std::endl;
|
||||
buffer << "\"layout\":" << info.pSubpasses[i].pColorAttachments[j].layout
|
||||
<< std::endl;
|
||||
buffer << "}" << std::endl;
|
||||
if (j < info.pSubpasses[i].colorAttachmentCount - 1) {
|
||||
buffer << ",";
|
||||
}
|
||||
buffer << std::endl;
|
||||
}
|
||||
buffer << "]";
|
||||
}
|
||||
|
||||
//------------Input-------------------
|
||||
if (info.pSubpasses[i].pInputAttachments) {
|
||||
buffer << "," << std::endl;
|
||||
buffer << "\"input_attachments\":[" << std::endl;
|
||||
for (uint32_t j = 0; j < info.pSubpasses[i].inputAttachmentCount; ++j) {
|
||||
buffer << "{" << std::endl;
|
||||
buffer << "\"attachement\":"
|
||||
<< info.pSubpasses[i].pInputAttachments[j].attachment << ","
|
||||
<< std::endl;
|
||||
buffer << "\"layout\":" << info.pSubpasses[i].pInputAttachments[j].layout
|
||||
<< std::endl;
|
||||
buffer << "}" << std::endl;
|
||||
if (j < info.pSubpasses[i].inputAttachmentCount - 1) {
|
||||
buffer << ",";
|
||||
}
|
||||
buffer << std::endl;
|
||||
}
|
||||
buffer << "]" << std::endl;
|
||||
}
|
||||
|
||||
buffer << "}";
|
||||
if (i < info.subpassCount - 1) {
|
||||
buffer << ",";
|
||||
}
|
||||
buffer << std::endl;
|
||||
}
|
||||
buffer << "]" << std::endl;
|
||||
|
||||
buffer << "}";
|
||||
file << buffer.str();
|
||||
}
|
||||
file.close();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef TNT_FILAMENT_BACKEND_VULKANRENDERPASSSTATESERIALIZER_H
|
||||
#define TNT_FILAMENT_BACKEND_VULKANRENDERPASSSTATESERIALIZER_H
|
||||
|
||||
#include "VulkanCommands.h"
|
||||
|
||||
#include <backend/DriverEnums.h>
|
||||
#include <backend/TargetBufferInfo.h>
|
||||
|
||||
#include <bluevk/BlueVK.h>
|
||||
#include <iostream>
|
||||
#include <type_traits>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
class VulkanRenderPassStateSerializer {
|
||||
public:
|
||||
VulkanRenderPassStateSerializer(VulkanRenderPassStateSerializer const&) = delete;
|
||||
VulkanRenderPassStateSerializer& operator=(VulkanRenderPassStateSerializer const&) = delete;
|
||||
|
||||
VulkanRenderPassStateSerializer(const VkRenderPassCreateInfo& info, uint32_t key);
|
||||
};
|
||||
} // namespace filament::backend
|
||||
|
||||
#endif //TNT_FILAMENT_BACKEND_VULKANRENDERPASSSTATESERIALIZER_H
|
||||
@@ -21,12 +21,14 @@
|
||||
|
||||
#include <utils/Panic.h>
|
||||
|
||||
#include "VulkanSamplerStateSerializer.h"
|
||||
|
||||
using namespace bluevk;
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
VulkanSamplerCache::VulkanSamplerCache(VkDevice device)
|
||||
: mDevice(device) {}
|
||||
VulkanSamplerCache::VulkanSamplerCache(VkDevice device, VulkanYcbcrConversionCache* conversionCache)
|
||||
: mDevice(device), mConversionCache(conversionCache) {}
|
||||
|
||||
VkSampler VulkanSamplerCache::getSampler(Params params) {
|
||||
auto iter = mCache.find(params);
|
||||
@@ -57,11 +59,16 @@ VkSampler VulkanSamplerCache::getSampler(Params params) {
|
||||
.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK,
|
||||
.unnormalizedCoordinates = VK_FALSE,
|
||||
};
|
||||
VulkanSamplerStateSerializer samplerSer(params,
|
||||
params.conversion != VK_NULL_HANDLE ? mConversionCache->getKey(params.conversion) : 0);
|
||||
|
||||
VkSampler sampler;
|
||||
VkResult result = vkCreateSampler(mDevice, &samplerInfo, VKALLOC, &sampler);
|
||||
FILAMENT_CHECK_POSTCONDITION(result == VK_SUCCESS) << "Unable to create sampler."
|
||||
<< " error=" << static_cast<int32_t>(result);
|
||||
mCache.insert({ params, sampler });
|
||||
SamplerHashFn hashFn;
|
||||
mSamplerToKey[sampler] = hashFn(params);
|
||||
return sampler;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,9 +17,11 @@
|
||||
#ifndef TNT_FILAMENT_BACKEND_VULKANSAMPLERCACHE_H
|
||||
#define TNT_FILAMENT_BACKEND_VULKANSAMPLERCACHE_H
|
||||
|
||||
#include "VulkanYcbcrConversionCache.h"
|
||||
#include <backend/DriverEnums.h>
|
||||
|
||||
#include <utils/Hash.h>
|
||||
#include <map>
|
||||
|
||||
#include <bluevk/BlueVK.h>
|
||||
#include <tsl/robin_map.h>
|
||||
@@ -37,11 +39,20 @@ public:
|
||||
|
||||
static_assert(sizeof(Params) == 16);
|
||||
|
||||
explicit VulkanSamplerCache(VkDevice device);
|
||||
explicit VulkanSamplerCache(VkDevice device, VulkanYcbcrConversionCache* conversionCache);
|
||||
VkSampler getSampler(Params params);
|
||||
uint32_t getKey(VkSampler sampler) {
|
||||
uint32_t key = 0;
|
||||
auto iter = mSamplerToKey.find(sampler);
|
||||
if (iter != mSamplerToKey.end()) {
|
||||
key = iter->second;
|
||||
}
|
||||
return key;
|
||||
}
|
||||
void terminate() noexcept;
|
||||
private:
|
||||
VkDevice mDevice;
|
||||
VulkanYcbcrConversionCache* mConversionCache;
|
||||
|
||||
struct SamplerEqualTo {
|
||||
bool operator()(Params lhs, Params rhs) const noexcept {
|
||||
@@ -51,6 +62,7 @@ private:
|
||||
};
|
||||
using SamplerHashFn = utils::hash::MurmurHashFn<Params>;
|
||||
tsl::robin_map<Params, VkSampler, SamplerHashFn, SamplerEqualTo> mCache;
|
||||
std::map<VkSampler, uint32_t> mSamplerToKey;
|
||||
};
|
||||
|
||||
} // namespace filament::backend
|
||||
|
||||
64
filament/backend/src/vulkan/VulkanSamplerStateSerializer.cpp
Normal file
64
filament/backend/src/vulkan/VulkanSamplerStateSerializer.cpp
Normal file
@@ -0,0 +1,64 @@
|
||||
#include "VulkanSamplerStateSerializer.h"
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <utils/Hash.h>
|
||||
|
||||
namespace filament::backend {
|
||||
VulkanYcbcrConversionSerializer::VulkanYcbcrConversionSerializer(
|
||||
const VulkanYcbcrConversionCache::Params& params) {
|
||||
using ConversionHashFn = utils::hash::MurmurHashFn<VulkanYcbcrConversionCache::Params>;
|
||||
ConversionHashFn hashFn;
|
||||
uint32_t key = hashFn(params);
|
||||
std::stringstream filename;
|
||||
filename << "ycbcr_conv_" << key << ".json";
|
||||
|
||||
std::ofstream file(filename.str());
|
||||
if (file.is_open()) {
|
||||
std::stringstream buffer;
|
||||
auto const& chroma = params.conversion;
|
||||
buffer << "{" << std::endl;
|
||||
buffer << "\"format\":" << params.format << "," << std::endl;
|
||||
buffer << "\"external_format\":" << params.externalFormat << "," << std::endl;
|
||||
buffer << "\"ycbcr_model\":" << uint8_t(chroma.ycbcrModel) << "," << std::endl;
|
||||
buffer << "\"ycbcr_range\":" << uint8_t(chroma.ycbcrRange) << "," << std::endl;
|
||||
buffer << "\"swizzle_array\":[" << uint8_t(chroma.r) << "," << uint8_t(chroma.g) << ","
|
||||
<< uint8_t(chroma.b) << "," << uint8_t(chroma.a) << "]," << std::endl;
|
||||
buffer << "\"x_chroma_offset\":" << uint8_t(chroma.xChromaOffset) << "," << std::endl;
|
||||
buffer << "\"y_chroma_offset\":" << uint8_t(chroma.yChromaOffset) << "," << std::endl;
|
||||
buffer << "\"chroma_filter\":" << uint8_t(chroma.chromaFilter) << std::endl;
|
||||
buffer << "}" << std::endl;
|
||||
|
||||
file << buffer.str();
|
||||
}
|
||||
file.close();
|
||||
}
|
||||
|
||||
VulkanSamplerStateSerializer::VulkanSamplerStateSerializer(const VulkanSamplerCache::Params& params, uint32_t ycbcr_conv_key) {
|
||||
using ConversionHashFn = utils::hash::MurmurHashFn<VulkanSamplerCache::Params>;
|
||||
ConversionHashFn hashFn;
|
||||
uint32_t key = hashFn(params);
|
||||
std::stringstream filename;
|
||||
filename << "sampler_" << key << ".json";
|
||||
|
||||
std::ofstream file(filename.str());
|
||||
if (file.is_open()) {
|
||||
std::stringstream buffer;
|
||||
auto const& samplerParams = params.sampler;
|
||||
buffer << "{" << std::endl;
|
||||
buffer << "\"filter_mag\":" << uint32_t(samplerParams.filterMag) << "," << std::endl;
|
||||
buffer << "\"filter_min\":" << uint32_t(samplerParams.filterMin) << "," << std::endl;
|
||||
buffer << "\"wrap_s\":" << uint32_t(samplerParams.wrapS) << "," << std::endl;
|
||||
buffer << "\"wrap_t\":" << uint32_t(samplerParams.wrapT) << "," << std::endl;
|
||||
buffer << "\"wrap_r\":" << uint32_t(samplerParams.wrapR) << "," << std::endl;
|
||||
buffer << "\"anisotropy_log2\":" << uint32_t(samplerParams.anisotropyLog2) << "," << std::endl;
|
||||
buffer << "\"compare_mode\":" << uint32_t(samplerParams.compareMode) << "," << std::endl;
|
||||
buffer << "\"compare_func\":" << uint32_t(samplerParams.compareFunc) << "," << std::endl;
|
||||
buffer << "\"ycbcr_conv_key\":" << ycbcr_conv_key << std::endl;
|
||||
buffer << "}" << std::endl;
|
||||
|
||||
file << buffer.str();
|
||||
}
|
||||
file.close();
|
||||
}
|
||||
|
||||
} // namespace filament::backend
|
||||
48
filament/backend/src/vulkan/VulkanSamplerStateSerializer.h
Normal file
48
filament/backend/src/vulkan/VulkanSamplerStateSerializer.h
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef TNT_FILAMENT_BACKEND_VULKANSAMPLERSTATESERIALIZER_H
|
||||
#define TNT_FILAMENT_BACKEND_VULKANSAMPLERSTATESERIALIZER_H
|
||||
|
||||
#include <backend/DriverEnums.h>
|
||||
#include "VulkanYcbcrConversionCache.h"
|
||||
#include "VulkanSamplerCache.h"
|
||||
|
||||
#include <bluevk/BlueVK.h>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
class VulkanYcbcrConversionSerializer {
|
||||
public:
|
||||
VulkanYcbcrConversionSerializer(VulkanYcbcrConversionSerializer const&) = delete;
|
||||
VulkanYcbcrConversionSerializer& operator=(VulkanYcbcrConversionSerializer const&) = delete;
|
||||
|
||||
VulkanYcbcrConversionSerializer(const VulkanYcbcrConversionCache::Params& params);
|
||||
};
|
||||
// VulkanPipelineStateSerializer stores to a file the pipeline states.
|
||||
class VulkanSamplerStateSerializer {
|
||||
public:
|
||||
VulkanSamplerStateSerializer(VulkanSamplerStateSerializer const&) = delete;
|
||||
VulkanSamplerStateSerializer& operator=(VulkanSamplerStateSerializer const&) = delete;
|
||||
|
||||
VulkanSamplerStateSerializer(const VulkanSamplerCache::Params& params, uint32_t ycbcr_conv_key);
|
||||
};
|
||||
}
|
||||
|
||||
#endif //TNT_FILAMENT_BACKEND_VULKANSAMPLERSTATESERIALIZER_H
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
|
||||
#include "VulkanYcbcrConversionCache.h"
|
||||
#include "VulkanSamplerStateSerializer.h"
|
||||
|
||||
#include "vulkan/VulkanConstants.h"
|
||||
#include "vulkan/utils/Conversion.h"
|
||||
@@ -53,6 +54,7 @@ VkSamplerYcbcrConversion VulkanYcbcrConversionCache::getConversion(
|
||||
.yChromaOffset = fvkutils::getChromaLocation(chroma.yChromaOffset),
|
||||
.chromaFilter = fvkutils::getFilter(chroma.chromaFilter),
|
||||
};
|
||||
VulkanYcbcrConversionSerializer ycbcr_ser(params);
|
||||
|
||||
// We could put this in the platform class, but that seems like a bit of an overkill
|
||||
#if defined(__ANDROID__)
|
||||
@@ -73,6 +75,8 @@ VkSamplerYcbcrConversion VulkanYcbcrConversionCache::getConversion(
|
||||
<< " error=" << static_cast<int32_t>(result);
|
||||
|
||||
mCache.insert({ params, conversion });
|
||||
ConversionHashFn hashFn;
|
||||
mConversionToKey[conversion] = hashFn(params);
|
||||
return conversion;
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
#include <bluevk/BlueVK.h>
|
||||
#include <tsl/robin_map.h>
|
||||
#include <map>
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
@@ -40,6 +41,14 @@ public:
|
||||
|
||||
explicit VulkanYcbcrConversionCache(VkDevice device);
|
||||
VkSamplerYcbcrConversion getConversion(Params params);
|
||||
uint32_t getKey(VkSamplerYcbcrConversion conv) {
|
||||
uint32_t key = 0;
|
||||
auto iter = mConversionToKey.find(conv);
|
||||
if (iter != mConversionToKey.end()) {
|
||||
key = iter->second;
|
||||
}
|
||||
return key;
|
||||
}
|
||||
void terminate() noexcept;
|
||||
|
||||
private:
|
||||
@@ -54,6 +63,7 @@ private:
|
||||
};
|
||||
using ConversionHashFn = utils::hash::MurmurHashFn<Params>;
|
||||
tsl::robin_map<Params, VkSamplerYcbcrConversion, ConversionHashFn, ConversionEqualTo> mCache;
|
||||
std::map<VkSamplerYcbcrConversion, uint32_t> mConversionToKey;
|
||||
};
|
||||
|
||||
} // namespace filament::backend
|
||||
|
||||
Reference in New Issue
Block a user