mirror of
https://github.com/doitsujin/dxvk.git
synced 2024-11-30 22:24:15 +01:00
[d3d11] Add support for DSV read-only flags
Games need this in order to use the depth buffer as both a framebuffer attachment and a shader resource.
This commit is contained in:
parent
c1efe2f6b5
commit
b31ebbb690
@ -1720,12 +1720,18 @@ namespace dxvk {
|
||||
// target bindings are updated. Set up the attachments.
|
||||
if (ppRenderTargetViews != nullptr || pDepthStencilView != nullptr) {
|
||||
for (UINT i = 0; i < m_state.om.renderTargetViews.size(); i++) {
|
||||
if (m_state.om.renderTargetViews.at(i) != nullptr)
|
||||
attachments.setColorTarget(i, m_state.om.renderTargetViews.at(i)->GetImageView());
|
||||
if (m_state.om.renderTargetViews.at(i) != nullptr) {
|
||||
attachments.setColorTarget(i,
|
||||
m_state.om.renderTargetViews.at(i)->GetImageView(),
|
||||
m_state.om.renderTargetViews.at(i)->GetRenderLayout());
|
||||
}
|
||||
}
|
||||
|
||||
if (m_state.om.depthStencilView != nullptr)
|
||||
attachments.setDepthTarget(m_state.om.depthStencilView->GetImageView());
|
||||
if (m_state.om.depthStencilView != nullptr) {
|
||||
attachments.setDepthTarget(
|
||||
m_state.om.depthStencilView->GetImageView(),
|
||||
m_state.om.depthStencilView->GetRenderLayout());
|
||||
}
|
||||
}
|
||||
|
||||
// Create and bind the framebuffer object to the context
|
||||
|
@ -45,6 +45,19 @@ namespace dxvk {
|
||||
return m_view;
|
||||
}
|
||||
|
||||
VkImageLayout GetRenderLayout() const {
|
||||
switch (m_desc.Flags & (D3D11_DSV_READ_ONLY_DEPTH | D3D11_DSV_READ_ONLY_STENCIL)) {
|
||||
default: // case 0
|
||||
return VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
||||
case D3D11_DSV_READ_ONLY_DEPTH:
|
||||
return VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL_KHR;
|
||||
case D3D11_DSV_READ_ONLY_STENCIL:
|
||||
return VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL_KHR;
|
||||
case D3D11_DSV_READ_ONLY_DEPTH | D3D11_DSV_READ_ONLY_STENCIL:
|
||||
return VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
Com<D3D11Device> m_device;
|
||||
|
@ -41,6 +41,11 @@ namespace dxvk {
|
||||
return m_view;
|
||||
}
|
||||
|
||||
VkImageLayout GetRenderLayout() const {
|
||||
// Currently no reason to use anything else
|
||||
return VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
Com<D3D11Device> m_device;
|
||||
|
@ -1371,6 +1371,15 @@ namespace dxvk {
|
||||
m_descInfos[i].image.imageView = res.imageView->handle();
|
||||
m_descInfos[i].image.imageLayout = res.imageView->imageInfo().layout;
|
||||
|
||||
// TODO try to reduce the runtime overhead of all these comparisons
|
||||
if (bindPoint == VK_PIPELINE_BIND_POINT_GRAPHICS) {
|
||||
DxvkAttachment depthAttachment = m_state.om.framebuffer->renderTargets().getDepthTarget();
|
||||
|
||||
if (depthAttachment.view != nullptr
|
||||
&& depthAttachment.view->image() == res.imageView->image())
|
||||
m_descInfos[i].image.imageLayout = depthAttachment.layout;
|
||||
}
|
||||
|
||||
m_cmd->trackResource(res.imageView);
|
||||
m_cmd->trackResource(res.imageView->image());
|
||||
} else {
|
||||
|
@ -58,7 +58,7 @@ namespace dxvk {
|
||||
|
||||
|
||||
struct DxvkOutputMergerState {
|
||||
Rc<DxvkFramebuffer> framebuffer;
|
||||
Rc<DxvkFramebuffer> framebuffer = nullptr;
|
||||
|
||||
DxvkBlendConstants blendConstants = { 0.0f, 0.0f, 0.0f, 0.0f };
|
||||
uint32_t stencilReference = 0;
|
||||
|
@ -10,21 +10,23 @@ namespace dxvk {
|
||||
DxvkRenderPassFormat result;
|
||||
|
||||
for (uint32_t i = 0; i < MaxNumRenderTargets; i++) {
|
||||
if (m_colorTargets.at(i) != nullptr) {
|
||||
if (m_colorTargets.at(i).view != nullptr) {
|
||||
result.setColorFormat(i, DxvkRenderTargetFormat {
|
||||
m_colorTargets.at(i)->info().format,
|
||||
m_colorTargets.at(i)->imageInfo().layout,
|
||||
m_colorTargets.at(i)->imageInfo().layout });
|
||||
result.setSampleCount(m_colorTargets.at(i)->image()->info().sampleCount);
|
||||
m_colorTargets.at(i).view->info().format,
|
||||
m_colorTargets.at(i).view->imageInfo().layout,
|
||||
m_colorTargets.at(i).view->imageInfo().layout,
|
||||
m_colorTargets.at(i).layout });
|
||||
result.setSampleCount(m_colorTargets.at(i).view->imageInfo().sampleCount);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_depthTarget != nullptr) {
|
||||
if (m_depthTarget.view != nullptr) {
|
||||
result.setDepthFormat(DxvkRenderTargetFormat {
|
||||
m_depthTarget->info().format,
|
||||
m_depthTarget->imageInfo().layout,
|
||||
m_depthTarget->imageInfo().layout });
|
||||
result.setSampleCount(m_depthTarget->image()->info().sampleCount);
|
||||
m_depthTarget.view->info().format,
|
||||
m_depthTarget.view->imageInfo().layout,
|
||||
m_depthTarget.view->imageInfo().layout,
|
||||
m_depthTarget.layout });
|
||||
result.setSampleCount(m_depthTarget.view->imageInfo().sampleCount);
|
||||
}
|
||||
|
||||
return result;
|
||||
@ -34,12 +36,12 @@ namespace dxvk {
|
||||
std::vector<VkImageView> DxvkRenderTargets::getAttachments() const {
|
||||
std::vector<VkImageView> result;
|
||||
|
||||
if (m_depthTarget != nullptr)
|
||||
result.push_back(m_depthTarget->handle());
|
||||
if (m_depthTarget.view != nullptr)
|
||||
result.push_back(m_depthTarget.view->handle());
|
||||
|
||||
for (uint32_t i = 0; i < MaxNumRenderTargets; i++) {
|
||||
if (m_colorTargets.at(i) != nullptr)
|
||||
result.push_back(m_colorTargets.at(i)->handle());
|
||||
if (m_colorTargets.at(i).view != nullptr)
|
||||
result.push_back(m_colorTargets.at(i).view->handle());
|
||||
}
|
||||
|
||||
return result;
|
||||
@ -47,12 +49,12 @@ namespace dxvk {
|
||||
|
||||
|
||||
DxvkFramebufferSize DxvkRenderTargets::getImageSize() const {
|
||||
if (m_depthTarget != nullptr)
|
||||
return this->renderTargetSize(m_depthTarget);
|
||||
if (m_depthTarget.view != nullptr)
|
||||
return this->renderTargetSize(m_depthTarget.view);
|
||||
|
||||
for (uint32_t i = 0; i < MaxNumRenderTargets; i++) {
|
||||
if (m_colorTargets.at(i) != nullptr)
|
||||
return this->renderTargetSize(m_colorTargets.at(i));
|
||||
if (m_colorTargets.at(i).view != nullptr)
|
||||
return this->renderTargetSize(m_colorTargets.at(i).view);
|
||||
}
|
||||
|
||||
return DxvkFramebufferSize { 0, 0, 0 };
|
||||
@ -60,10 +62,10 @@ namespace dxvk {
|
||||
|
||||
|
||||
bool DxvkRenderTargets::hasAttachments() const {
|
||||
bool result = m_depthTarget != nullptr;
|
||||
bool result = m_depthTarget.view != nullptr;
|
||||
|
||||
for (uint32_t i = 0; (i < MaxNumRenderTargets) && !result; i++)
|
||||
result |= m_colorTargets.at(i) != nullptr;
|
||||
result |= m_colorTargets.at(i).view != nullptr;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -19,6 +19,12 @@ namespace dxvk {
|
||||
};
|
||||
|
||||
|
||||
struct DxvkAttachment {
|
||||
Rc<DxvkImageView> view = nullptr;
|
||||
VkImageLayout layout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* \brief Render target description
|
||||
*
|
||||
@ -40,7 +46,7 @@ namespace dxvk {
|
||||
* \param [in] id Color attachment ID
|
||||
* \returns Render target view
|
||||
*/
|
||||
Rc<DxvkImageView> getColorTarget(uint32_t id) const {
|
||||
DxvkAttachment getColorTarget(uint32_t id) const {
|
||||
return m_colorTargets.at(id);
|
||||
}
|
||||
|
||||
@ -48,7 +54,7 @@ namespace dxvk {
|
||||
* \brief Retrieves depth-stencil target
|
||||
* \returns Depth-stencil target view
|
||||
*/
|
||||
Rc<DxvkImageView> getDepthTarget() const {
|
||||
DxvkAttachment getDepthTarget() const {
|
||||
return m_depthTarget;
|
||||
}
|
||||
|
||||
@ -57,17 +63,25 @@ namespace dxvk {
|
||||
*
|
||||
* \param [in] id Color attachment ID
|
||||
* \param [in] view Render target view
|
||||
* \param [in] layout Layout to use for rendering
|
||||
*/
|
||||
void setColorTarget(uint32_t id, const Rc<DxvkImageView>& view) {
|
||||
m_colorTargets.at(id) = view;
|
||||
void setColorTarget(
|
||||
uint32_t id,
|
||||
const Rc<DxvkImageView>& view,
|
||||
VkImageLayout layout) {
|
||||
m_colorTargets.at(id) = { view, layout };
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Sets depth-stencil target
|
||||
*
|
||||
* \param [in] layout Layout to use for rendering
|
||||
* \param [in] view Depth-stencil target view
|
||||
*/
|
||||
void setDepthTarget(const Rc<DxvkImageView>& view) {
|
||||
m_depthTarget = view;
|
||||
void setDepthTarget(
|
||||
const Rc<DxvkImageView>& view,
|
||||
VkImageLayout layout) {
|
||||
m_depthTarget = { view, layout };
|
||||
}
|
||||
|
||||
/**
|
||||
@ -102,8 +116,8 @@ namespace dxvk {
|
||||
|
||||
private:
|
||||
|
||||
std::array<Rc<DxvkImageView>, MaxNumRenderTargets> m_colorTargets;
|
||||
Rc<DxvkImageView> m_depthTarget;
|
||||
std::array<DxvkAttachment, MaxNumRenderTargets> m_colorTargets;
|
||||
DxvkAttachment m_depthTarget;
|
||||
|
||||
DxvkFramebufferSize renderTargetSize(
|
||||
const Rc<DxvkImageView>& renderTarget) const;
|
||||
|
@ -1,58 +1,28 @@
|
||||
#include <algorithm>
|
||||
|
||||
#include "dxvk_renderpass.h"
|
||||
|
||||
namespace dxvk {
|
||||
|
||||
bool DxvkRenderTargetFormat::operator == (const DxvkRenderTargetFormat& other) const {
|
||||
return this->format == other.format
|
||||
&& this->initialLayout == other.initialLayout
|
||||
&& this->finalLayout == other.finalLayout;
|
||||
bool DxvkRenderPassFormat::matchesFormat(const DxvkRenderPassFormat& other) const {
|
||||
bool equal = m_samples == other.m_samples;
|
||||
|
||||
equal = m_depth.format == other.m_depth.format
|
||||
&& m_depth.initialLayout == other.m_depth.initialLayout
|
||||
&& m_depth.finalLayout == other.m_depth.finalLayout
|
||||
&& m_depth.renderLayout == other.m_depth.renderLayout;
|
||||
|
||||
for (uint32_t i = 0; i < MaxNumRenderTargets && equal; i++) {
|
||||
equal &= m_color[i].format == other.m_color[i].format
|
||||
&& m_color[i].initialLayout == other.m_color[i].initialLayout
|
||||
&& m_color[i].finalLayout == other.m_color[i].finalLayout
|
||||
&& m_color[i].renderLayout == other.m_color[i].renderLayout;
|
||||
}
|
||||
|
||||
|
||||
bool DxvkRenderTargetFormat::operator != (const DxvkRenderTargetFormat& other) const {
|
||||
return !this->operator == (other);
|
||||
}
|
||||
|
||||
|
||||
size_t DxvkRenderTargetFormat::hash() const {
|
||||
std::hash<VkFormat> fhash;
|
||||
std::hash<VkImageLayout> lhash;
|
||||
|
||||
DxvkHashState result;
|
||||
result.add(fhash(this->format));
|
||||
result.add(lhash(this->initialLayout));
|
||||
result.add(lhash(this->finalLayout));
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
size_t DxvkRenderPassFormat::hash() const {
|
||||
std::hash<VkSampleCountFlagBits> shash;
|
||||
|
||||
DxvkHashState result;
|
||||
for (uint32_t i = 0; i < MaxNumRenderTargets; i++)
|
||||
result.add(m_color[i].hash());
|
||||
|
||||
result.add(m_depth.hash());
|
||||
result.add(shash(m_samples));
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
bool DxvkRenderPassFormat::operator == (const DxvkRenderPassFormat& other) const {
|
||||
bool equal = m_depth == other.m_depth
|
||||
&& m_samples == other.m_samples;
|
||||
for (uint32_t i = 0; i < MaxNumRenderTargets && !equal; i++)
|
||||
equal = m_color[i] == other.m_color[i];
|
||||
return equal;
|
||||
}
|
||||
|
||||
|
||||
bool DxvkRenderPassFormat::operator != (const DxvkRenderPassFormat& other) const {
|
||||
return !this->operator == (other);
|
||||
}
|
||||
|
||||
|
||||
DxvkRenderPass::DxvkRenderPass(
|
||||
const Rc<vk::DeviceFn>& vkd,
|
||||
const DxvkRenderPassFormat& fmt)
|
||||
@ -79,7 +49,7 @@ namespace dxvk {
|
||||
desc.finalLayout = depthFmt.finalLayout;
|
||||
|
||||
depthRef.attachment = attachments.size();
|
||||
depthRef.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
||||
depthRef.layout = depthFmt.renderLayout;
|
||||
|
||||
attachments.push_back(desc);
|
||||
}
|
||||
@ -195,14 +165,19 @@ namespace dxvk {
|
||||
const DxvkRenderPassFormat& fmt) {
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
|
||||
auto rp = m_renderPasses.find(fmt);
|
||||
Rc<DxvkRenderPass> renderPass = nullptr;
|
||||
|
||||
if (rp != m_renderPasses.end())
|
||||
return rp->second;
|
||||
for (uint32_t i = 0; i < m_renderPasses.size() && renderPass == nullptr; i++) {
|
||||
if (m_renderPasses[i]->matchesFormat(fmt))
|
||||
renderPass = m_renderPasses[i];
|
||||
}
|
||||
|
||||
auto result = this->createRenderPass(fmt);
|
||||
m_renderPasses.insert(std::make_pair(fmt, result));
|
||||
return result;
|
||||
if (renderPass != nullptr)
|
||||
return renderPass;
|
||||
|
||||
renderPass = this->createRenderPass(fmt);
|
||||
m_renderPasses.push_back(renderPass);
|
||||
return renderPass;
|
||||
}
|
||||
|
||||
|
||||
|
@ -19,11 +19,7 @@ namespace dxvk {
|
||||
VkFormat format = VK_FORMAT_UNDEFINED;
|
||||
VkImageLayout initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
VkImageLayout finalLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
|
||||
bool operator == (const DxvkRenderTargetFormat& other) const;
|
||||
bool operator != (const DxvkRenderTargetFormat& other) const;
|
||||
|
||||
size_t hash() const;
|
||||
VkImageLayout renderLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
};
|
||||
|
||||
|
||||
@ -97,13 +93,12 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Computes the hash
|
||||
* \returns Resulting hash
|
||||
* \brief Checks whether two render pass formats are compatible
|
||||
*
|
||||
* \param [in] other The render pass format to compare to
|
||||
* \returns \c true if the render pass formats are compatible
|
||||
*/
|
||||
size_t hash() const;
|
||||
|
||||
bool operator == (const DxvkRenderPassFormat& other) const;
|
||||
bool operator != (const DxvkRenderPassFormat& other) const;
|
||||
bool matchesFormat(const DxvkRenderPassFormat& other) const;
|
||||
|
||||
private:
|
||||
|
||||
@ -147,6 +142,19 @@ namespace dxvk {
|
||||
return m_format.getSampleCount();
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Checks render pass format compatibility
|
||||
*
|
||||
* This render pass object can be used with compatible render
|
||||
* pass formats. Two render pass formats are compatible if the
|
||||
* used attachments match in image format and layout.
|
||||
* \param [in] format The render pass format to test
|
||||
* \returns \c true if the formats match
|
||||
*/
|
||||
bool matchesFormat(const DxvkRenderPassFormat& format) const {
|
||||
return m_format.matchesFormat(format);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
Rc<vk::DeviceFn> m_vkd;
|
||||
@ -183,10 +191,7 @@ namespace dxvk {
|
||||
Rc<vk::DeviceFn> m_vkd;
|
||||
|
||||
std::mutex m_mutex;
|
||||
std::unordered_map<
|
||||
DxvkRenderPassFormat,
|
||||
Rc<DxvkRenderPass>,
|
||||
DxvkHash> m_renderPasses;
|
||||
std::vector<Rc<DxvkRenderPass>> m_renderPasses;
|
||||
|
||||
Rc<DxvkRenderPass> createRenderPass(
|
||||
const DxvkRenderPassFormat& fmt);
|
||||
|
@ -179,7 +179,8 @@ namespace dxvk {
|
||||
Rc<DxvkImageView> iview = m_device->createImageView(image, viewInfo);
|
||||
|
||||
DxvkRenderTargets renderTargets;
|
||||
renderTargets.setColorTarget(0, iview);
|
||||
renderTargets.setColorTarget(0, iview,
|
||||
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
||||
|
||||
m_framebuffers.at(i) = new DxvkFramebuffer(
|
||||
m_vkd, m_renderPass, renderTargets);
|
||||
|
@ -69,6 +69,24 @@ namespace dxvk::util {
|
||||
}
|
||||
|
||||
|
||||
inline bool operator == (
|
||||
const VkImageSubresourceRange& a,
|
||||
const VkImageSubresourceRange& b) {
|
||||
return a.aspectMask == b.aspectMask
|
||||
&& a.baseMipLevel == b.baseMipLevel
|
||||
&& a.levelCount == b.levelCount
|
||||
&& a.baseArrayLayer == b.baseArrayLayer
|
||||
&& a.layerCount == b.layerCount;
|
||||
}
|
||||
|
||||
|
||||
inline bool operator != (
|
||||
const VkImageSubresourceRange& a,
|
||||
const VkImageSubresourceRange& b) {
|
||||
return !operator == (a, b);
|
||||
}
|
||||
|
||||
|
||||
inline bool operator == (VkExtent3D a, VkExtent3D b) {
|
||||
return a.width == b.width
|
||||
&& a.height == b.height
|
||||
|
@ -177,7 +177,8 @@ namespace dxvk::hud {
|
||||
m_renderTargetView = m_device->createImageView(m_renderTarget, viewInfo);
|
||||
|
||||
DxvkRenderTargets framebufferInfo;
|
||||
framebufferInfo.setColorTarget(0, m_renderTargetView);
|
||||
framebufferInfo.setColorTarget(0, m_renderTargetView,
|
||||
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
||||
|
||||
m_renderTargetFbo = m_device->createFramebuffer(framebufferInfo);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user