1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-01-31 14:52:11 +01:00

[dxvk] Remove render pass and framebuffer objects

This commit is contained in:
Philip Rebohle 2022-07-02 21:32:17 +02:00
parent e3a63d4faa
commit e8f3d9b040
No known key found for this signature in database
GPG Key ID: C8CC613427A31C99
17 changed files with 15 additions and 731 deletions

View File

@ -259,14 +259,6 @@ namespace dxvk {
}
void cmdBeginRenderPass(
const VkRenderPassBeginInfo* pRenderPassBegin,
VkSubpassContents contents) {
m_vkd->vkCmdBeginRenderPass(m_execBuffer,
pRenderPassBegin, contents);
}
void cmdBeginTransformFeedback(
uint32_t firstBuffer,
uint32_t bufferCount,
@ -600,11 +592,6 @@ namespace dxvk {
}
void cmdEndRenderPass() {
m_vkd->vkCmdEndRenderPass(m_execBuffer);
}
void cmdEndTransformFeedback(
uint32_t firstBuffer,
uint32_t bufferCount,

View File

@ -4420,8 +4420,7 @@ namespace dxvk {
: DxvkContextFlag::GpDirtyStencilRef);
// Retrieve and bind actual Vulkan pipeline handle
VkPipeline pipeline = m_state.gp.pipeline->getPipelineHandle(
m_state.gp.state, m_state.om.framebufferInfo.renderPass());
VkPipeline pipeline = m_state.gp.pipeline->getPipelineHandle(m_state.gp.state);
if (unlikely(!pipeline))
return false;
@ -4660,10 +4659,7 @@ namespace dxvk {
DxvkFramebufferInfo DxvkContext::makeFramebufferInfo(
const DxvkRenderTargets& renderTargets) {
auto renderPassFormat = DxvkFramebufferInfo::getRenderPassFormat(renderTargets);
auto renderPassObject = m_common->renderPassPool().getRenderPass(renderPassFormat);
return DxvkFramebufferInfo(renderTargets, m_device->getDefaultFramebufferSize(), renderPassObject);
return DxvkFramebufferInfo(renderTargets, m_device->getDefaultFramebufferSize());
}
@ -5527,18 +5523,6 @@ namespace dxvk {
}
Rc<DxvkFramebuffer> DxvkContext::lookupFramebuffer(
const DxvkFramebufferInfo& framebufferInfo) {
DxvkFramebufferKey key = framebufferInfo.key();
size_t idx = key.hash() % m_framebufferCache.size();
if (m_framebufferCache[idx] == nullptr || !m_framebufferCache[idx]->key().eq(key))
m_framebufferCache[idx] = m_device->createFramebuffer(framebufferInfo);
return m_framebufferCache[idx];
}
Rc<DxvkBuffer> DxvkContext::createZeroBuffer(
VkDeviceSize size) {
if (m_zeroBuffer != nullptr && m_zeroBuffer->info().size >= size)

View File

@ -1156,7 +1156,6 @@ namespace dxvk {
std::array<DxvkShaderResourceSlot, MaxNumResourceSlots> m_rc;
std::array<DxvkGraphicsPipeline*, 4096> m_gpLookupCache = { };
std::array<DxvkComputePipeline*, 256> m_cpLookupCache = { };
std::array<Rc<DxvkFramebuffer>, 512> m_framebufferCache = { };
void blitImageFb(
const Rc<DxvkImage>& dstImage,
@ -1411,9 +1410,6 @@ namespace dxvk {
DxvkComputePipeline* lookupComputePipeline(
const DxvkComputePipelineShaders& shaders);
Rc<DxvkFramebuffer> lookupFramebuffer(
const DxvkFramebufferInfo& framebufferInfo);
Rc<DxvkBuffer> createZeroBuffer(
VkDeviceSize size);

View File

@ -102,12 +102,6 @@ namespace dxvk {
}
Rc<DxvkFramebuffer> DxvkDevice::createFramebuffer(
const DxvkFramebufferInfo& info) {
return new DxvkFramebuffer(m_vkd, info);
}
Rc<DxvkBuffer> DxvkDevice::createBuffer(
const DxvkBufferCreateInfo& createInfo,
VkMemoryPropertyFlags memoryType) {

View File

@ -258,15 +258,6 @@ namespace dxvk {
VkQueryControlFlags flags,
uint32_t index);
/**
* \brief Creates framebuffer for a set of render targets
*
* \param [in] info Framebuffer info
* \returns The framebuffer object
*/
Rc<DxvkFramebuffer> createFramebuffer(
const DxvkFramebufferInfo& info);
/**
* \brief Creates a buffer object
*

View File

@ -9,11 +9,9 @@ namespace dxvk {
DxvkFramebufferInfo::DxvkFramebufferInfo(
const DxvkRenderTargets& renderTargets,
const DxvkFramebufferSize& defaultSize,
DxvkRenderPass* renderPass)
const DxvkFramebufferSize& defaultSize)
: m_renderTargets (renderTargets),
m_renderSize (computeRenderSize(defaultSize)),
m_renderPass (renderPass) {
m_renderSize (computeRenderSize(defaultSize)) {
for (uint32_t i = 0; i < MaxNumRenderTargets; i++) {
if (m_renderTargets.color[i].view != nullptr) {
@ -70,24 +68,6 @@ namespace dxvk {
}
DxvkFramebufferKey DxvkFramebufferInfo::key() const {
DxvkFramebufferKey result = { };
for (uint32_t i = 0; i < MaxNumRenderTargets; i++) {
if (m_renderTargets.color[i].view != nullptr)
result.colorViews[i] = m_renderTargets.color[i].view->cookie();
}
if (m_renderTargets.depth.view != nullptr)
result.depthView = m_renderTargets.depth.view->cookie();
if (result.renderPass)
result.renderPass = m_renderPass->getDefaultHandle();
return result;
}
DxvkRtInfo DxvkFramebufferInfo::getRtInfo() const {
VkFormat depthStencilFormat = VK_FORMAT_UNDEFINED;
VkImageAspectFlags depthStencilReadOnlyAspects = 0;
@ -109,27 +89,6 @@ namespace dxvk {
}
DxvkRenderPassFormat DxvkFramebufferInfo::getRenderPassFormat(const DxvkRenderTargets& renderTargets) {
DxvkRenderPassFormat format;
for (uint32_t i = 0; i < MaxNumRenderTargets; i++) {
if (renderTargets.color[i].view != nullptr) {
format.sampleCount = renderTargets.color[i].view->imageInfo().sampleCount;
format.color[i].format = renderTargets.color[i].view->info().format;
format.color[i].layout = renderTargets.color[i].layout;
}
}
if (renderTargets.depth.view != nullptr) {
format.sampleCount = renderTargets.depth.view->imageInfo().sampleCount;
format.depth.format = renderTargets.depth.view->info().format;
format.depth.layout = renderTargets.depth.layout;
}
return format;
}
DxvkFramebufferSize DxvkFramebufferInfo::computeRenderSize(
const DxvkFramebufferSize& defaultSize) const {
// Some games bind render targets of a different size and
@ -163,40 +122,4 @@ namespace dxvk {
return DxvkFramebufferSize { extent.width, extent.height, layers };
}
DxvkFramebuffer::DxvkFramebuffer(
const Rc<vk::DeviceFn>& vkd,
const DxvkFramebufferInfo& info)
: m_vkd(vkd), m_key(info.key()) {
std::array<VkImageView, MaxNumRenderTargets + 1> views;
uint32_t attachmentCount = 0;
for (uint32_t i = 0; i < MaxNumRenderTargets; i++) {
if (info.getColorTarget(i).view != nullptr)
views[attachmentCount++] = info.getColorTarget(i).view->handle();
}
if (info.getDepthTarget().view != nullptr)
views[attachmentCount++] = info.getDepthTarget().view->handle();
VkFramebufferCreateInfo fbInfo;
fbInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
fbInfo.pNext = nullptr;
fbInfo.flags = 0;
fbInfo.renderPass = info.renderPass()->getDefaultHandle();
fbInfo.attachmentCount = attachmentCount;
fbInfo.pAttachments = views.data();
fbInfo.width = info.size().width;
fbInfo.height = info.size().height;
fbInfo.layers = info.size().layers;
if (m_vkd->vkCreateFramebuffer(m_vkd->device(), &fbInfo, nullptr, &m_handle) != VK_SUCCESS)
Logger::err("DxvkFramebuffer: Failed to create framebuffer object");
}
DxvkFramebuffer::~DxvkFramebuffer() {
m_vkd->vkDestroyFramebuffer(m_vkd->device(), m_handle, nullptr);
}
}

View File

@ -94,8 +94,7 @@ namespace dxvk {
DxvkFramebufferInfo(
const DxvkRenderTargets& renderTargets,
const DxvkFramebufferSize& defaultSize,
DxvkRenderPass* renderPass);
const DxvkFramebufferSize& defaultSize);
~DxvkFramebufferInfo();
@ -115,14 +114,6 @@ namespace dxvk {
return m_renderSize;
}
/**
* \brief Render pass
* \returns Render pass
*/
DxvkRenderPass* renderPass() const {
return m_renderPass;
}
/**
* \brief Framebuffer sample count
*
@ -220,35 +211,17 @@ namespace dxvk {
*/
bool isWritable(uint32_t attachmentIndex, VkImageAspectFlags aspects) const;
/**
* \brief Generates framebuffer key
* \returns Framebuffer key
*/
DxvkFramebufferKey key() const;
/**
* \brief Generates render target state
* \returns Render target state info
*/
DxvkRtInfo getRtInfo() const;
/**
* \brief Generatess render pass format
*
* This render pass format can be used to
* look up a compatible render pass.
* \param [in] renderTargets Render targets
* \returns The render pass format
*/
static DxvkRenderPassFormat getRenderPassFormat(
const DxvkRenderTargets& renderTargets);
private:
DxvkRenderTargets m_renderTargets;
DxvkFramebufferSize m_renderSize = { 0u, 0u, 0u };
VkSampleCountFlags m_sampleCount = 0;
DxvkRenderPass* m_renderPass;
uint32_t m_attachmentCount = 0;
std::array<int32_t, MaxNumRenderTargets + 1> m_attachments;
@ -261,46 +234,4 @@ namespace dxvk {
};
/**
* \brief Framebuffer
*
* A framebuffer either stores a set of image views
* that will be used as render targets, or in case
* no render targets are attached, fixed dimensions.
*/
class DxvkFramebuffer : public DxvkResource {
public:
DxvkFramebuffer(
const Rc<vk::DeviceFn>& vkd,
const DxvkFramebufferInfo& info);
~DxvkFramebuffer();
/**
* \brief Framebuffer handle
* \returns Framebuffer handle
*/
VkFramebuffer handle() const {
return m_handle;
}
/**
* \brief Framebuffer key
*/
const DxvkFramebufferKey& key() const {
return m_key;
}
private:
Rc<vk::DeviceFn> m_vkd;
VkFramebuffer m_handle;
DxvkFramebufferKey m_key;
};
}

View File

@ -49,8 +49,7 @@ namespace dxvk {
VkPipeline DxvkGraphicsPipeline::getPipelineHandle(
const DxvkGraphicsPipelineStateInfo& state,
const DxvkRenderPass* renderPass) {
const DxvkGraphicsPipelineStateInfo& state) {
DxvkGraphicsPipelineInstance* instance = this->findInstance(state);
if (unlikely(!instance)) {

View File

@ -106,7 +106,6 @@ namespace dxvk {
* \brief Checks for matching pipeline state
*
* \param [in] stateVector Graphics pipeline state
* \param [in] renderPass Render pass handle
* \returns \c true if the specialization is compatible
*/
bool isCompatible(
@ -193,12 +192,10 @@ namespace dxvk {
* Retrieves a pipeline handle for the given pipeline
* state. If necessary, a new pipeline will be created.
* \param [in] state Pipeline state vector
* \param [in] renderPass The render pass
* \returns Pipeline handle
*/
VkPipeline getPipelineHandle(
const DxvkGraphicsPipelineStateInfo& state,
const DxvkRenderPass* renderPass);
const DxvkGraphicsPipelineStateInfo& state);
/**
* \brief Compiles a pipeline

View File

@ -24,8 +24,7 @@ namespace dxvk {
DxvkObjects(DxvkDevice* device)
: m_device (device),
m_memoryManager (device),
m_renderPassPool (device),
m_pipelineManager (device, &m_renderPassPool),
m_pipelineManager (device),
m_eventPool (device),
m_queryPool (device),
m_dummyResources (device) {
@ -36,10 +35,6 @@ namespace dxvk {
return m_memoryManager;
}
DxvkRenderPassPool& renderPassPool() {
return m_renderPassPool;
}
DxvkPipelineManager& pipelineManager() {
return m_pipelineManager;
}
@ -81,7 +76,6 @@ namespace dxvk {
DxvkDevice* m_device;
DxvkMemoryAllocator m_memoryManager;
DxvkRenderPassPool m_renderPassPool;
DxvkPipelineManager m_pipelineManager;
DxvkGpuEventPool m_eventPool;

View File

@ -5,14 +5,13 @@
namespace dxvk {
DxvkPipelineManager::DxvkPipelineManager(
DxvkDevice* device,
DxvkRenderPassPool* passManager)
DxvkDevice* device)
: m_device (device),
m_cache (new DxvkPipelineCache(device->vkd())) {
std::string useStateCache = env::getEnvVar("DXVK_STATE_CACHE");
if (useStateCache != "0" && device->config().enableStateCache)
m_stateCache = new DxvkStateCache(device, this, passManager);
m_stateCache = new DxvkStateCache(device, this);
}

View File

@ -38,8 +38,7 @@ namespace dxvk {
public:
DxvkPipelineManager(
DxvkDevice* device,
DxvkRenderPassPool* passManager);
DxvkDevice* device);
~DxvkPipelineManager();

View File

@ -1,332 +0,0 @@
#include <algorithm>
#include "dxvk_device.h"
#include "dxvk_renderpass.h"
namespace dxvk {
bool DxvkRenderPassFormat::eq(const DxvkRenderPassFormat& fmt) const {
bool eq = sampleCount == fmt.sampleCount;
for (uint32_t i = 0; i < MaxNumRenderTargets && eq; i++) {
eq &= color[i].format == fmt.color[i].format
&& color[i].layout == fmt.color[i].layout;
}
eq &= depth.format == fmt.depth.format
&& depth.layout == fmt.depth.layout;
return eq;
}
size_t DxvkRenderPassFormat::hash() const {
DxvkHashState state;
state.add(uint32_t(sampleCount));
for (uint32_t i = 0; i < MaxNumRenderTargets; i++) {
state.add(uint32_t(color[i].format));
state.add(uint32_t(color[i].layout));
}
state.add(uint32_t(depth.format));
state.add(uint32_t(depth.layout));
return state;
}
DxvkRenderPass::DxvkRenderPass(
const Rc<vk::DeviceFn>& vkd,
const DxvkRenderPassFormat& fmt)
: m_vkd(vkd), m_format(fmt),
m_default(createRenderPass(DxvkRenderPassOps())) {
}
DxvkRenderPass::~DxvkRenderPass() {
m_vkd->vkDestroyRenderPass(m_vkd->device(), m_default, nullptr);
for (const auto& i : m_instances) {
m_vkd->vkDestroyRenderPass(
m_vkd->device(), i.handle, nullptr);
}
}
bool DxvkRenderPass::hasCompatibleFormat(const DxvkRenderPassFormat& fmt) const {
return m_format.eq(fmt);
}
VkRenderPass DxvkRenderPass::getHandle(const DxvkRenderPassOps& ops) {
VkRenderPass handle = this->findHandle(ops);
if (unlikely(!handle)) {
std::lock_guard<dxvk::mutex> lock(m_mutex);
handle = this->findHandle(ops);
if (!handle) {
handle = this->createRenderPass(ops);
m_instances.insert({ ops, handle });
}
}
return handle;
}
VkRenderPass DxvkRenderPass::findHandle(const DxvkRenderPassOps& ops) {
for (const auto& i : m_instances) {
if (compareOps(i.ops, ops))
return i.handle;
}
return VK_NULL_HANDLE;
}
VkRenderPass DxvkRenderPass::createRenderPass(const DxvkRenderPassOps& ops) {
std::vector<VkAttachmentDescription> attachments;
VkAttachmentReference depthRef;
std::array<VkAttachmentReference, MaxNumRenderTargets> colorRef;
// Render passes may not require the previous
// contents of the attachments to be preserved.
for (uint32_t i = 0; i < MaxNumRenderTargets; i++) {
if (m_format.color[i].format != VK_FORMAT_UNDEFINED) {
VkAttachmentDescription desc;
desc.flags = 0;
desc.format = m_format.color[i].format;
desc.samples = m_format.sampleCount;
desc.loadOp = ops.colorOps[i].loadOp;
desc.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
desc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
desc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
desc.initialLayout = ops.colorOps[i].loadLayout;
desc.finalLayout = ops.colorOps[i].storeLayout;
colorRef[i].attachment = attachments.size();
colorRef[i].layout = m_format.color[i].layout;
attachments.push_back(desc);
} else {
colorRef[i].attachment = VK_ATTACHMENT_UNUSED;
colorRef[i].layout = VK_IMAGE_LAYOUT_UNDEFINED;
}
}
if (m_format.depth.format != VK_FORMAT_UNDEFINED) {
VkAttachmentDescription desc;
desc.flags = 0;
desc.format = m_format.depth.format;
desc.samples = m_format.sampleCount;
desc.loadOp = ops.depthOps.loadOpD;
desc.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
desc.stencilLoadOp = ops.depthOps.loadOpS;
desc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
desc.initialLayout = ops.depthOps.loadLayout;
desc.finalLayout = ops.depthOps.storeLayout;
depthRef.attachment = attachments.size();
depthRef.layout = m_format.depth.layout;
attachments.push_back(desc);
} else {
depthRef.attachment = VK_ATTACHMENT_UNUSED;
depthRef.layout = VK_IMAGE_LAYOUT_UNDEFINED;
}
VkSubpassDescription subpass;
subpass.flags = 0;
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
subpass.inputAttachmentCount = 0;
subpass.pInputAttachments = nullptr;
subpass.colorAttachmentCount = colorRef.size();
subpass.pColorAttachments = colorRef.data();
subpass.pResolveAttachments = nullptr;
subpass.pDepthStencilAttachment = &depthRef;
subpass.preserveAttachmentCount = 0;
subpass.pPreserveAttachments = nullptr;
if (m_format.depth.format == VK_FORMAT_UNDEFINED)
subpass.pDepthStencilAttachment = nullptr;
std::array<VkSubpassDependency, 3> subpassDeps;
uint32_t subpassDepCount = 0;
VkPipelineStageFlags renderStages = 0;
VkAccessFlags renderAccess = 0;
if (m_format.depth.format) {
renderStages |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT
| VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
VkImageAspectFlags loadAspects = 0;
if (ops.depthOps.loadOpD == VK_ATTACHMENT_LOAD_OP_LOAD)
loadAspects |= VK_IMAGE_ASPECT_DEPTH_BIT;
if (ops.depthOps.loadOpS == VK_ATTACHMENT_LOAD_OP_LOAD)
loadAspects |= VK_IMAGE_ASPECT_STENCIL_BIT;
if (loadAspects & imageFormatInfo(m_format.depth.format)->aspectMask)
renderAccess |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT;
if (m_format.depth.layout != VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL)
renderAccess |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
if (m_format.depth.layout != VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) {
renderStages |= VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
renderAccess |= VK_ACCESS_SHADER_READ_BIT;
}
}
for (uint32_t i = 0; i < MaxNumRenderTargets; i++) {
if (!m_format.color[i].format)
continue;
renderStages |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
renderAccess |= VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
if (ops.colorOps[i].loadOp == VK_ATTACHMENT_LOAD_OP_LOAD)
renderAccess |= VK_ACCESS_COLOR_ATTACHMENT_READ_BIT;
}
if (renderStages) {
subpassDeps[subpassDepCount++] = {
VK_SUBPASS_EXTERNAL, 0,
renderStages, renderStages,
0, renderAccess };
}
if (ops.barrier.srcStages & (
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT |
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT)) {
subpassDeps[subpassDepCount++] = { 0, 0,
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
VK_ACCESS_SHADER_READ_BIT,
VK_DEPENDENCY_BY_REGION_BIT };
}
if (ops.barrier.srcStages && ops.barrier.dstStages) {
subpassDeps[subpassDepCount++] = {
0, VK_SUBPASS_EXTERNAL,
ops.barrier.srcStages,
ops.barrier.dstStages,
ops.barrier.srcAccess,
ops.barrier.dstAccess, 0 };
}
VkRenderPassCreateInfo info;
info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
info.pNext = nullptr;
info.flags = 0;
info.attachmentCount = attachments.size();
info.pAttachments = attachments.data();
info.subpassCount = 1;
info.pSubpasses = &subpass;
info.dependencyCount = subpassDepCount;
info.pDependencies = subpassDepCount ? subpassDeps.data() : nullptr;
VkRenderPass renderPass = VK_NULL_HANDLE;
if (m_vkd->vkCreateRenderPass(m_vkd->device(), &info, nullptr, &renderPass) != VK_SUCCESS) {
Logger::err("DxvkRenderPass: Failed to create render pass object");
return VK_NULL_HANDLE;
}
return renderPass;
}
bool DxvkRenderPass::compareOps(
const DxvkRenderPassOps& a,
const DxvkRenderPassOps& b) {
bool eq = a.barrier.srcStages == b.barrier.srcStages
&& a.barrier.srcAccess == b.barrier.srcAccess
&& a.barrier.dstStages == b.barrier.dstStages
&& a.barrier.dstAccess == b.barrier.dstAccess;
if (eq) {
eq &= a.depthOps.loadOpD == b.depthOps.loadOpD
&& a.depthOps.loadOpS == b.depthOps.loadOpS
&& a.depthOps.loadLayout == b.depthOps.loadLayout
&& a.depthOps.storeLayout == b.depthOps.storeLayout;
}
for (uint32_t i = 0; i < MaxNumRenderTargets && eq; i++) {
eq &= a.colorOps[i].loadOp == b.colorOps[i].loadOp
&& a.colorOps[i].loadLayout == b.colorOps[i].loadLayout
&& a.colorOps[i].storeLayout == b.colorOps[i].storeLayout;
}
return eq;
}
DxvkRenderPassPool::DxvkRenderPassPool(const DxvkDevice* device)
: m_device(device) {
}
DxvkRenderPassPool::~DxvkRenderPassPool() {
}
DxvkRenderPass* DxvkRenderPassPool::getRenderPass(const DxvkRenderPassFormat& fmt) {
std::lock_guard<dxvk::mutex> lock(m_mutex);
auto entry = m_renderPasses.find(fmt);
if (entry != m_renderPasses.end())
return &entry->second;
auto result = m_renderPasses.emplace(std::piecewise_construct,
std::tuple(fmt),
std::tuple(m_device->vkd(), fmt));
return &result.first->second;
}
bool DxvkRenderPassPool::validateRenderPassFormat(
const DxvkRenderPassFormat& fmt) {
Rc<DxvkAdapter> adapter = m_device->adapter();
if (fmt.depth.format) {
VkFormatProperties depthInfo = adapter->formatProperties(fmt.depth.format);
VkFormatFeatureFlags depthFlags = depthInfo.linearTilingFeatures | depthInfo.optimalTilingFeatures;
if (!(depthFlags & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT))
return false;
if (fmt.depth.layout != VK_IMAGE_LAYOUT_GENERAL
&& fmt.depth.layout != VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL
&& fmt.depth.layout != VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL
&& fmt.depth.layout != VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL
&& fmt.depth.layout != VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL)
return false;
}
for (uint32_t i = 0; i < MaxNumRenderTargets; i++) {
if (fmt.color[i].format) {
VkFormatProperties colorInfo = adapter->formatProperties(fmt.color[i].format);
VkFormatFeatureFlags colorFlags = colorInfo.linearTilingFeatures | colorInfo.optimalTilingFeatures;
if (!(colorFlags & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT))
return false;
if (fmt.color[i].layout != VK_IMAGE_LAYOUT_GENERAL
&& fmt.color[i].layout != VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)
return false;
}
}
return true;
}
}

View File

@ -14,35 +14,6 @@ namespace dxvk {
class DxvkDevice;
/**
* \brief Format and layout for a render target
*
* Stores the image format of the attachment and
* the image layout that is used while rendering.
*/
struct DxvkAttachmentFormat {
VkFormat format = VK_FORMAT_UNDEFINED;
VkImageLayout layout = VK_IMAGE_LAYOUT_UNDEFINED;
};
/**
* \brief Render pass format
*
* Stores the attachment formats for all depth and
* color attachments, as well as the sample count.
*/
struct DxvkRenderPassFormat {
VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT;
DxvkAttachmentFormat depth;
DxvkAttachmentFormat color[MaxNumRenderTargets];
bool eq(const DxvkRenderPassFormat& fmt) const;
size_t hash() const;
};
/**
* \brief Color attachment transitions
*
@ -97,148 +68,4 @@ namespace dxvk {
DxvkColorAttachmentOps colorOps[MaxNumRenderTargets];
};
/**
* \brief Render pass object
*
* Manages a set of compatible render passes, i.e.
* render passes which share the same format but
* may differ in their attachment operations.
*/
class DxvkRenderPass {
public:
DxvkRenderPass(
const Rc<vk::DeviceFn>& vkd,
const DxvkRenderPassFormat& fmt);
~DxvkRenderPass();
/**
* \brief Retrieves render pass format
* \returns The render pass format
*/
DxvkRenderPassFormat format() const {
return m_format;
}
/**
* \brief Checks whether a format is compatible
*
* Two render pass formats are considered compatible
* if all the relevant attachment formats match.
* \param [in] fmt The render pass format to check
* \returns \c true if this render pass is compatible.
*/
bool hasCompatibleFormat(
const DxvkRenderPassFormat& fmt) const;
/**
* \brief Retrieves sample count
*
* If no sample count has been explicitly specitied,
* this will return \c VK_SAMPLE_COUNT_1_BIT.
* \returns Sample count
*/
VkSampleCountFlagBits getSampleCount() const {
return m_format.sampleCount;
}
/**
* \brief Returns handle of default render pass
*
* The default render pass handle should be used to
* create pipelines and framebuffer objects. It can
* \e not be used for \c vkCmdBeginRenderPass calls.
* \returns The default render pass handle
*/
VkRenderPass getDefaultHandle() const {
return m_default;
}
/**
* \brief Returns handle to a specialized render pass
*
* Returns a handle to a render pass with the given
* set of parameters. This should be used for calls
* to \c vkCmdBeginRenderPass.
* \param [in] ops Attachment ops
* \returns Render pass handle
*/
VkRenderPass getHandle(
const DxvkRenderPassOps& ops);
private:
struct Instance {
DxvkRenderPassOps ops;
VkRenderPass handle;
};
Rc<vk::DeviceFn> m_vkd;
DxvkRenderPassFormat m_format;
VkRenderPass m_default;
dxvk::mutex m_mutex;
sync::List<Instance> m_instances;
VkRenderPass findHandle(
const DxvkRenderPassOps& ops);
VkRenderPass createRenderPass(
const DxvkRenderPassOps& ops);
static bool compareOps(
const DxvkRenderPassOps& a,
const DxvkRenderPassOps& b);
};
/**
* \brief Render pass pool
*
* Manages render pass objects. For each render
* pass format, a new render pass object will
* be created, but no two render pass objects
* will have the same format.
*/
class DxvkRenderPassPool {
public:
DxvkRenderPassPool(const DxvkDevice* device);
~DxvkRenderPassPool();
/**
* \brief Retrieves a render pass object
*
* \param [in] fmt The render pass format
* \returns Matching render pass object
*/
DxvkRenderPass* getRenderPass(
const DxvkRenderPassFormat& fmt);
/**
* \brief Validates render pass format
*
* \param [in] fmt The render pass format
* \returns \c true if the format is supported
*/
bool validateRenderPassFormat(
const DxvkRenderPassFormat& fmt);
private:
const DxvkDevice* m_device;
dxvk::mutex m_mutex;
std::unordered_map<
DxvkRenderPassFormat,
DxvkRenderPass,
DxvkHash, DxvkEq> m_renderPasses;
};
}

View File

@ -200,11 +200,9 @@ namespace dxvk {
DxvkStateCache::DxvkStateCache(
DxvkDevice* device,
DxvkPipelineManager* pipeManager,
DxvkRenderPassPool* passManager)
DxvkPipelineManager* pipeManager)
: m_device (device),
m_pipeManager (pipeManager),
m_passManager (passManager) {
m_pipeManager (pipeManager) {
bool newFile = !readCacheFile();
if (newFile) {

View File

@ -29,8 +29,7 @@ namespace dxvk {
DxvkStateCache(
DxvkDevice* device,
DxvkPipelineManager* pipeManager,
DxvkRenderPassPool* passManager);
DxvkPipelineManager* pipeManager);
~DxvkStateCache();
@ -94,7 +93,6 @@ namespace dxvk {
DxvkDevice* m_device;
DxvkPipelineManager* m_pipeManager;
DxvkRenderPassPool* m_passManager;
std::vector<DxvkStateCacheEntry> m_entries;
std::atomic<bool> m_stopThreads = { false };

View File

@ -93,7 +93,6 @@ dxvk_src = files([
'dxvk_pipelayout.cpp',
'dxvk_pipemanager.cpp',
'dxvk_queue.cpp',
'dxvk_renderpass.cpp',
'dxvk_resource.cpp',
'dxvk_sampler.cpp',
'dxvk_shader.cpp',