[d3d11] Implemented depth-stencil binding and clear methods

This commit is contained in:
Philip Rebohle 2017-12-09 03:53:42 +01:00
parent a43bb134e0
commit b3c391d071
8 changed files with 116 additions and 50 deletions

View File

@ -276,17 +276,15 @@ namespace dxvk {
ID3D11RenderTargetView* pRenderTargetView,
const FLOAT ColorRGBA[4]) {
auto rtv = static_cast<D3D11RenderTargetView*>(pRenderTargetView);
const Rc<DxvkImageView> dxvkView = rtv->GetDXVKImageView();
const Rc<DxvkImage> dxvkImage = dxvkView->image();
const Rc<DxvkImageView> dxvkView = rtv->GetDXVKImageView();
// Find out whether the given attachment is currently bound
// or not, and if it is, which attachment index it has.
int32_t attachmentIndex = -1;
if (m_state.om.framebuffer != nullptr) {
attachmentIndex = m_state.om.framebuffer
->renderTargets().getAttachmentId(dxvkView);
for (uint32_t i = 0; i < m_state.om.renderTargetViews.size(); i++) {
if (m_state.om.renderTargetViews.at(i) == rtv)
attachmentIndex = i;
}
// Copy the clear color into a clear value structure.
@ -309,10 +307,10 @@ namespace dxvk {
VkClearRect clearRect;
clearRect.rect.offset.x = 0;
clearRect.rect.offset.y = 0;
clearRect.rect.extent.width = dxvkImage->info().extent.width;
clearRect.rect.extent.height = dxvkImage->info().extent.height;
clearRect.rect.extent.width = dxvkView->imageInfo().extent.width;
clearRect.rect.extent.height = dxvkView->imageInfo().extent.height;
clearRect.baseArrayLayer = 0;
clearRect.layerCount = dxvkImage->info().numLayers;
clearRect.layerCount = dxvkView->imageInfo().numLayers;
if (m_parent->GetFeatureLevel() < D3D_FEATURE_LEVEL_10_0)
clearRect.layerCount = 1;
@ -321,7 +319,7 @@ namespace dxvk {
} else {
// Image is not bound to the pipeline. We can still clear
// it, but we'll have to use a generic clear function.
m_context->clearColorImage(dxvkImage,
m_context->clearColorImage(dxvkView->image(),
clearValue, dxvkView->subresources());
}
}
@ -346,7 +344,45 @@ namespace dxvk {
UINT ClearFlags,
FLOAT Depth,
UINT8 Stencil) {
Logger::err("D3D11DeviceContext::ClearDepthStencilView: Not implemented");
auto dsv = static_cast<D3D11DepthStencilView*>(pDepthStencilView);
const Rc<DxvkImageView> dxvkView = dsv->GetDXVKImageView();
VkClearDepthStencilValue clearValue;
clearValue.depth = Depth;
clearValue.stencil = Stencil;
if (m_state.om.depthStencilView == dsv) {
// Image is bound to the pipeline for rendering. We can
// use the clear function that operates on attachments.
VkClearAttachment clearInfo;
clearInfo.aspectMask = 0;
clearInfo.colorAttachment = 0;
clearInfo.clearValue.depthStencil = clearValue;
if (ClearFlags & D3D11_CLEAR_DEPTH)
clearInfo.aspectMask |= VK_IMAGE_ASPECT_DEPTH_BIT;
if (ClearFlags & D3D11_CLEAR_STENCIL)
clearInfo.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
// Clear the full area
VkClearRect clearRect;
clearRect.rect.offset.x = 0;
clearRect.rect.offset.y = 0;
clearRect.rect.extent.width = dxvkView->imageInfo().extent.width;
clearRect.rect.extent.height = dxvkView->imageInfo().extent.height;
clearRect.baseArrayLayer = 0;
clearRect.layerCount = dxvkView->imageInfo().numLayers;
// FIXME Is this correct? Docs don't say anything
if (m_parent->GetFeatureLevel() < D3D_FEATURE_LEVEL_10_0)
clearRect.layerCount = 1;
m_context->clearRenderTarget(clearInfo, clearRect);
} else {
m_context->clearDepthStencilImage(dxvkView->image(),
clearValue, dxvkView->subresources());
}
}
@ -1109,7 +1145,6 @@ namespace dxvk {
UINT NumViews,
ID3D11RenderTargetView* const* ppRenderTargetViews,
ID3D11DepthStencilView* pDepthStencilView) {
// Update state vector for OMGetRenderTargets
for (UINT i = 0; i < m_state.om.renderTargetViews.size(); i++) {
D3D11RenderTargetView* view = nullptr;
@ -1119,6 +1154,9 @@ namespace dxvk {
m_state.om.renderTargetViews.at(i) = view;
}
m_state.om.depthStencilView = static_cast<D3D11DepthStencilView*>(pDepthStencilView);
// TODO unbind overlapping shader resource views
Rc<DxvkFramebuffer> framebuffer = nullptr;
@ -1134,15 +1172,13 @@ namespace dxvk {
attachments.setColorTarget(i, m_state.om.renderTargetViews.at(i)->GetDXVKImageView());
}
// TODO implement depth-stencil views
if (pDepthStencilView != nullptr)
Logger::err("D3D11DeviceContext::OMSetRenderTargets: Depth-stencil view not supported");
if (m_state.om.depthStencilView != nullptr)
attachments.setDepthTarget(m_state.om.depthStencilView->GetDXVKImageView());
framebuffer = m_device->createFramebuffer(attachments);
}
// Bind the framebuffer object to the context
m_state.om.framebuffer = framebuffer;
m_context->bindFramebuffer(framebuffer);
}

View File

@ -74,8 +74,7 @@ namespace dxvk {
struct D3D11ContextStateOM {
std::array<Com<D3D11RenderTargetView>, D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT> renderTargetViews;
Rc<DxvkFramebuffer> framebuffer;
Com<D3D11DepthStencilView> depthStencilView;
};

View File

@ -194,6 +194,18 @@ namespace dxvk {
}
void DxvkCommandList::cmdClearDepthStencilImage(
VkImage image,
VkImageLayout imageLayout,
const VkClearDepthStencilValue* pDepthStencil,
uint32_t rangeCount,
const VkImageSubresourceRange* pRanges) {
m_vkd->vkCmdClearDepthStencilImage(m_buffer,
image, imageLayout, pDepthStencil,
rangeCount, pRanges);
}
void DxvkCommandList::cmdCopyBuffer(
VkBuffer srcBuffer,
VkBuffer dstBuffer,

View File

@ -117,6 +117,13 @@ namespace dxvk {
uint32_t rangeCount,
const VkImageSubresourceRange* pRanges);
void cmdClearDepthStencilImage(
VkImage image,
VkImageLayout imageLayout,
const VkClearDepthStencilValue* pDepthStencil,
uint32_t rangeCount,
const VkImageSubresourceRange* pRanges);
void cmdCopyBuffer(
VkBuffer srcBuffer,
VkBuffer dstBuffer,

View File

@ -229,6 +229,38 @@ namespace dxvk {
}
void DxvkContext::clearDepthStencilImage(
const Rc<DxvkImage>& image,
const VkClearDepthStencilValue& value,
const VkImageSubresourceRange& subresources) {
this->renderPassEnd();
if (image->info().layout != VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) {
m_barriers.accessImage(image, subresources,
VK_IMAGE_LAYOUT_UNDEFINED, 0, 0,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_ACCESS_TRANSFER_WRITE_BIT);
m_barriers.recordCommands(m_cmd);
}
m_cmd->cmdClearDepthStencilImage(image->handle(),
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
&value, 1, &subresources);
m_barriers.accessImage(image, subresources,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_ACCESS_TRANSFER_WRITE_BIT,
image->info().layout,
image->info().stages,
image->info().access);
m_barriers.recordCommands(m_cmd);
m_cmd->trackResource(image);
}
void DxvkContext::clearRenderTarget(
const VkClearAttachment& attachment,
const VkClearRect& clearArea) {

View File

@ -155,6 +155,18 @@ namespace dxvk {
const VkClearColorValue& value,
const VkImageSubresourceRange& subresources);
/**
* \brief Clears subresources of a depth-stencil image
*
* \param [in] image The image to clear
* \param [in] value Clear value
* \param [in] subresources Subresources to clear
*/
void clearDepthStencilImage(
const Rc<DxvkImage>& image,
const VkClearDepthStencilValue& value,
const VkImageSubresourceRange& subresources);
/**
* \brief Clears an active render target
*

View File

@ -53,26 +53,6 @@ namespace dxvk {
}
int32_t DxvkRenderTargets::getAttachmentId(
const Rc<DxvkImageView>& view) const {
if (view == nullptr)
return -1;
if (m_depthTarget == view)
return 0;
uint32_t colorAttachmentBaseId =
m_depthTarget == nullptr ? 0 : 1;
for (uint32_t i = 0; i < MaxNumRenderTargets; i++) {
if (m_colorTargets.at(i) == view)
return i + colorAttachmentBaseId;
}
return -1;
}
DxvkFramebufferSize DxvkRenderTargets::renderTargetSize(
const Rc<DxvkImageView>& renderTarget) const {
auto extent = renderTarget->image()->info().extent;

View File

@ -94,18 +94,6 @@ namespace dxvk {
*/
DxvkFramebufferSize getImageSize() const;
/**
* \brief Retrieves the ID of an attachment
*
* This can be used to locate a color attachment
* or the depth-stencil attachment. Returns -1
* if the given view is not an attachment.
* \param [in] view View to find
* \returns Attachment ID, or \c -1
*/
int32_t getAttachmentId(
const Rc<DxvkImageView>& view) const;
private:
std::array<Rc<DxvkImageView>, MaxNumRenderTargets> m_colorTargets;