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:
parent
1fd037cf29
commit
5b725205ef
@ -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,
|
||||||
|
@ -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
|
||||||
*
|
*
|
||||||
|
Loading…
Reference in New Issue
Block a user