1
0
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:
Philip Rebohle 2018-02-06 17:31:23 +01:00
parent c1efe2f6b5
commit b31ebbb690
No known key found for this signature in database
GPG Key ID: C8CC613427A31C99
12 changed files with 152 additions and 103 deletions

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -1333,7 +1333,7 @@ namespace dxvk {
void DxvkContext::updateShaderResources(
VkPipelineBindPoint bindPoint,
const Rc<DxvkPipelineLayout>& layout) {
const Rc<DxvkPipelineLayout>& layout) {
DxvkBindingState& bs =
bindPoint == VK_PIPELINE_BIND_POINT_GRAPHICS
? m_state.gp.state.bsBindingState
@ -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 {

View File

@ -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;

View File

@ -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;
}

View File

@ -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;

View File

@ -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 DxvkRenderTargetFormat::operator != (const DxvkRenderTargetFormat& other) const {
return !this->operator == (other);
}
size_t DxvkRenderTargetFormat::hash() const {
std::hash<VkFormat> fhash;
std::hash<VkImageLayout> lhash;
bool DxvkRenderPassFormat::matchesFormat(const DxvkRenderPassFormat& other) const {
bool equal = m_samples == other.m_samples;
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;
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;
DxvkHashState result;
for (uint32_t i = 0; i < MaxNumRenderTargets; i++)
result.add(m_color[i].hash());
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;
}
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;
}

View File

@ -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;
@ -182,11 +190,8 @@ namespace dxvk {
Rc<vk::DeviceFn> m_vkd;
std::mutex m_mutex;
std::unordered_map<
DxvkRenderPassFormat,
Rc<DxvkRenderPass>,
DxvkHash> m_renderPasses;
std::mutex m_mutex;
std::vector<Rc<DxvkRenderPass>> m_renderPasses;
Rc<DxvkRenderPass> createRenderPass(
const DxvkRenderPassFormat& fmt);

View File

@ -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);

View File

@ -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

View File

@ -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);
}