1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2024-12-12 13:08:50 +01:00

[dxvk] Introduce DxvkFramebufferInfo

Stores all info that is currently held by the DxvkFramebuffer class,
but is not heap-allocated and will not create an actual framebuffer
object.
This commit is contained in:
Philip Rebohle 2021-11-03 16:07:46 +01:00
parent 1fd037cf29
commit 5b725205ef
No known key found for this signature in database
GPG Key ID: C8CC613427A31C99
2 changed files with 288 additions and 2 deletions

View File

@ -2,6 +2,129 @@
namespace dxvk { namespace dxvk {
DxvkFramebufferInfo::DxvkFramebufferInfo() {
}
DxvkFramebufferInfo::DxvkFramebufferInfo(
const DxvkRenderTargets& renderTargets,
const DxvkFramebufferSize& defaultSize,
DxvkRenderPass* renderPass)
: m_renderTargets (renderTargets),
m_renderSize (computeRenderSize(defaultSize)),
m_renderPass (renderPass) {
for (uint32_t i = 0; i < MaxNumRenderTargets; i++) {
if (m_renderTargets.color[i].view != nullptr) {
m_attachments[m_attachmentCount++] = i;
m_sampleCount = m_renderTargets.color[i].view->imageInfo().sampleCount;
}
}
if (m_renderTargets.depth.view != nullptr) {
m_attachments[m_attachmentCount++] = -1;
m_sampleCount = m_renderTargets.depth.view->imageInfo().sampleCount;
}
}
DxvkFramebufferInfo::~DxvkFramebufferInfo() {
}
int32_t DxvkFramebufferInfo::findAttachment(const Rc<DxvkImageView>& view) const {
for (uint32_t i = 0; i < m_attachmentCount; i++) {
if (getAttachment(i).view->matchesView(view))
return int32_t(i);
}
return -1;
}
bool DxvkFramebufferInfo::hasTargets(const DxvkRenderTargets& renderTargets) {
bool eq = m_renderTargets.depth.view == renderTargets.depth.view
&& m_renderTargets.depth.layout == renderTargets.depth.layout;
for (uint32_t i = 0; i < MaxNumRenderTargets && eq; i++) {
eq &= m_renderTargets.color[i].view == renderTargets.color[i].view
&& m_renderTargets.color[i].layout == renderTargets.color[i].layout;
}
return eq;
}
bool DxvkFramebufferInfo::isFullSize(const Rc<DxvkImageView>& view) const {
return m_renderSize.width == view->mipLevelExtent(0).width
&& m_renderSize.height == view->mipLevelExtent(0).height
&& m_renderSize.layers == view->info().numLayers;
}
bool DxvkFramebufferInfo::isWritable(uint32_t attachmentIndex, VkImageAspectFlags aspects) const {
VkImageAspectFlags writableAspects = vk::getWritableAspectsForLayout(getAttachment(attachmentIndex).layout);
return (writableAspects & aspects) == aspects;
}
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
// expect it to work, so we'll compute the minimum size
DxvkFramebufferSize minSize = defaultSize;
if (m_renderTargets.depth.view != nullptr) {
DxvkFramebufferSize depthSize = this->computeRenderTargetSize(m_renderTargets.depth.view);
minSize.width = std::min(minSize.width, depthSize.width);
minSize.height = std::min(minSize.height, depthSize.height);
minSize.layers = std::min(minSize.layers, depthSize.layers);
}
for (uint32_t i = 0; i < MaxNumRenderTargets; i++) {
if (m_renderTargets.color[i].view != nullptr) {
DxvkFramebufferSize colorSize = this->computeRenderTargetSize(m_renderTargets.color[i].view);
minSize.width = std::min(minSize.width, colorSize.width);
minSize.height = std::min(minSize.height, colorSize.height);
minSize.layers = std::min(minSize.layers, colorSize.layers);
}
}
return minSize;
}
DxvkFramebufferSize DxvkFramebufferInfo::computeRenderTargetSize(
const Rc<DxvkImageView>& renderTarget) const {
auto extent = renderTarget->mipLevelExtent(0);
auto layers = renderTarget->info().numLayers;
return DxvkFramebufferSize { extent.width, extent.height, layers };
}
DxvkFramebuffer::DxvkFramebuffer( DxvkFramebuffer::DxvkFramebuffer(
const Rc<vk::DeviceFn>& vkd, const Rc<vk::DeviceFn>& vkd,
DxvkRenderPass* renderPass, DxvkRenderPass* renderPass,

View File

@ -50,8 +50,171 @@ namespace dxvk {
VkImageLayout color[MaxNumRenderTargets]; VkImageLayout color[MaxNumRenderTargets];
VkImageLayout depth; VkImageLayout depth;
}; };
/**
* \brief Framebuffer info
*
* Stores metadata about the current framebuffer,
* without actually creating a framebuffer object.
*/
class DxvkFramebufferInfo {
public:
DxvkFramebufferInfo();
DxvkFramebufferInfo(
const DxvkRenderTargets& renderTargets,
const DxvkFramebufferSize& defaultSize,
DxvkRenderPass* renderPass);
~DxvkFramebufferInfo();
/**
* \brief Framebuffer size
* \returns Framebuffer size
*/
DxvkFramebufferSize size() const {
return m_renderSize;
}
/**
* \brief Render pass
* \returns Render pass
*/
DxvkRenderPass* renderPass() const {
return m_renderPass;
}
/**
* \brief Framebuffer sample count
*
* Returns the sample count of the color
* and depth-stencil attachments, or 0 if
* there are no attachments.
* \returns Sample count
*/
VkSampleCountFlags getSampleCount() const {
return m_sampleCount;
}
/**
* \brief Depth-stencil target
* \returns Depth-stencil target
*/
const DxvkAttachment& getDepthTarget() const {
return m_renderTargets.depth;
}
/**
* \brief Color target
*
* \param [in] id Target Index
* \returns The color target
*/
const DxvkAttachment& getColorTarget(uint32_t id) const {
return m_renderTargets.color[id];
}
/**
* \brief Number of framebuffer attachment
* \returns Total attachment count
*/
uint32_t numAttachments() const {
return m_attachmentCount;
}
/**
* \brief Queries color attachment index of a given attachment
* \returns The index, or -1 if the given attachment is the depth attachment
*/
const int32_t getColorAttachmentIndex(uint32_t id) const {
return m_attachments[id];
}
/**
* \brief Retrieves attachment by index
*
* \param [in] id Framebuffer attachment ID
* \returns The framebuffer attachment
*/
const DxvkAttachment& getAttachment(uint32_t id) const {
int32_t idx = getColorAttachmentIndex(id);
return idx < 0 ? m_renderTargets.depth : m_renderTargets.color[idx];
}
/**
* \brief Finds attachment index by view
*
* Color attachments start at 0
* \param [in] view Image view
* \returns Attachment index
*/
int32_t findAttachment(const Rc<DxvkImageView>& view) const;
/**
* \brief Checks whether the framebuffer's targets match
*
* \param [in] renderTargets Render targets to check
* \returns \c true if the render targets are the same
* as the ones used for this framebuffer object.
*/
bool hasTargets(const DxvkRenderTargets& renderTargets);
/**
* \brief Checks whether view and framebuffer sizes match
*
* Tests whether the size of the framebuffer is the same
* as the size of one of its views. This may be \c false
* when mixing attachments with mismatched dimensions.
* \param [in] view Image view to test
* \returns \c true if \c view has the same size as
* the framebuffer.
*/
bool isFullSize(const Rc<DxvkImageView>& view) const;
/**
* \brief Checks whether an attachment is writable
*
* Needed for certain clear optimizations.
* \param [in] attachmentIndex Attachment to check
* \param [in] aspects Aspect mask to check
* \returns \c true if all aspects can be written for the given attachment
*/
bool isWritable(uint32_t attachmentIndex, VkImageAspectFlags aspects) 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;
DxvkFramebufferSize computeRenderSize(
const DxvkFramebufferSize& defaultSize) const;
DxvkFramebufferSize computeRenderTargetSize(
const Rc<DxvkImageView>& renderTarget) const;
};
/** /**
* \brief Framebuffer * \brief Framebuffer
* *