[d3d11] Move Clear* methods to D3D11CommonContext

This commit is contained in:
Philip Rebohle 2022-08-03 20:47:31 +02:00
parent 50942cd2d9
commit 751d7467df
No known key found for this signature in database
GPG Key ID: C8CC613427A31C99
4 changed files with 450 additions and 445 deletions

View File

@ -79,427 +79,6 @@ namespace dxvk {
}
void STDMETHODCALLTYPE D3D11DeviceContext::ClearRenderTargetView(
ID3D11RenderTargetView* pRenderTargetView,
const FLOAT ColorRGBA[4]) {
D3D10DeviceLock lock = LockContext();
auto rtv = static_cast<D3D11RenderTargetView*>(pRenderTargetView);
if (!rtv)
return;
auto view = rtv->GetImageView();
auto color = ConvertColorValue(ColorRGBA, view->formatInfo());
EmitCs([
cClearValue = color,
cImageView = std::move(view)
] (DxvkContext* ctx) {
ctx->clearRenderTarget(
cImageView,
VK_IMAGE_ASPECT_COLOR_BIT,
cClearValue);
});
}
void STDMETHODCALLTYPE D3D11DeviceContext::ClearUnorderedAccessViewUint(
ID3D11UnorderedAccessView* pUnorderedAccessView,
const UINT Values[4]) {
D3D10DeviceLock lock = LockContext();
auto uav = static_cast<D3D11UnorderedAccessView*>(pUnorderedAccessView);
if (!uav)
return;
// Gather UAV format info. We'll use this to determine
// whether we need to create a temporary view or not.
D3D11_UNORDERED_ACCESS_VIEW_DESC uavDesc;
uav->GetDesc(&uavDesc);
VkFormat uavFormat = m_parent->LookupFormat(uavDesc.Format, DXGI_VK_FORMAT_MODE_ANY).Format;
VkFormat rawFormat = m_parent->LookupFormat(uavDesc.Format, DXGI_VK_FORMAT_MODE_RAW).Format;
if (uavFormat != rawFormat && rawFormat == VK_FORMAT_UNDEFINED) {
Logger::err(str::format("D3D11: ClearUnorderedAccessViewUint: No raw format found for ", uavFormat));
return;
}
VkClearValue clearValue;
// R11G11B10 is a special case since there's no corresponding
// integer format with the same bit layout. Use R32 instead.
if (uavFormat == VK_FORMAT_B10G11R11_UFLOAT_PACK32) {
clearValue.color.uint32[0] = ((Values[0] & 0x7FF) << 0)
| ((Values[1] & 0x7FF) << 11)
| ((Values[2] & 0x3FF) << 22);
clearValue.color.uint32[1] = 0;
clearValue.color.uint32[2] = 0;
clearValue.color.uint32[3] = 0;
} else {
clearValue.color.uint32[0] = Values[0];
clearValue.color.uint32[1] = Values[1];
clearValue.color.uint32[2] = Values[2];
clearValue.color.uint32[3] = Values[3];
}
if (uav->GetResourceType() == D3D11_RESOURCE_DIMENSION_BUFFER) {
// In case of raw and structured buffers as well as typed
// buffers that can be used for atomic operations, we can
// use the fast Vulkan buffer clear function.
Rc<DxvkBufferView> bufferView = uav->GetBufferView();
if (bufferView->info().format == VK_FORMAT_R32_UINT
|| bufferView->info().format == VK_FORMAT_R32_SINT
|| bufferView->info().format == VK_FORMAT_R32_SFLOAT
|| bufferView->info().format == VK_FORMAT_B10G11R11_UFLOAT_PACK32) {
EmitCs([
cClearValue = clearValue.color.uint32[0],
cDstSlice = bufferView->slice()
] (DxvkContext* ctx) {
ctx->clearBuffer(
cDstSlice.buffer(),
cDstSlice.offset(),
cDstSlice.length(),
cClearValue);
});
} else {
// Create a view with an integer format if necessary
if (uavFormat != rawFormat) {
DxvkBufferViewCreateInfo info = bufferView->info();
info.format = rawFormat;
bufferView = m_device->createBufferView(
bufferView->buffer(), info);
}
EmitCs([
cClearValue = clearValue,
cDstView = bufferView
] (DxvkContext* ctx) {
ctx->clearBufferView(
cDstView, 0,
cDstView->elementCount(),
cClearValue.color);
});
}
} else {
Rc<DxvkImageView> imageView = uav->GetImageView();
// If the clear value is zero, we can use the original view regardless of
// the format since the bit pattern will not change in any supported format.
bool isZeroClearValue = !(clearValue.color.uint32[0] | clearValue.color.uint32[1]
| clearValue.color.uint32[2] | clearValue.color.uint32[3]);
// Check if we can create an image view with the given raw format. If not,
// we'll have to use a fallback using a texel buffer view and buffer copies.
bool isViewCompatible = uavFormat == rawFormat;
if (!isViewCompatible && (imageView->imageInfo().flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT)) {
uint32_t formatCount = imageView->imageInfo().viewFormatCount;
isViewCompatible = formatCount == 0;
for (uint32_t i = 0; i < formatCount && !isViewCompatible; i++)
isViewCompatible = imageView->imageInfo().viewFormats[i] == rawFormat;
}
if (isViewCompatible || isZeroClearValue) {
// Create a view with an integer format if necessary
if (uavFormat != rawFormat && !isZeroClearValue) {
DxvkImageViewCreateInfo info = imageView->info();
info.format = rawFormat;
imageView = m_device->createImageView(imageView->image(), info);
}
EmitCs([
cClearValue = clearValue,
cDstView = imageView
] (DxvkContext* ctx) {
ctx->clearImageView(cDstView,
VkOffset3D { 0, 0, 0 },
cDstView->mipLevelExtent(0),
VK_IMAGE_ASPECT_COLOR_BIT,
cClearValue);
});
} else {
DxvkBufferCreateInfo bufferInfo;
bufferInfo.size = imageView->formatInfo()->elementSize
* imageView->info().numLayers
* util::flattenImageExtent(imageView->mipLevelExtent(0));
bufferInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT
| VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT;
bufferInfo.stages = VK_PIPELINE_STAGE_TRANSFER_BIT
| VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
bufferInfo.access = VK_ACCESS_TRANSFER_READ_BIT
| VK_ACCESS_SHADER_WRITE_BIT;
Rc<DxvkBuffer> buffer = m_device->createBuffer(bufferInfo,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
DxvkBufferViewCreateInfo bufferViewInfo;
bufferViewInfo.format = rawFormat;
bufferViewInfo.rangeOffset = 0;
bufferViewInfo.rangeLength = bufferInfo.size;
Rc<DxvkBufferView> bufferView = m_device->createBufferView(buffer,
bufferViewInfo);
EmitCs([
cDstView = std::move(imageView),
cSrcView = std::move(bufferView),
cClearValue = clearValue.color
] (DxvkContext* ctx) {
ctx->clearBufferView(
cSrcView, 0,
cSrcView->elementCount(),
cClearValue);
ctx->copyBufferToImage(cDstView->image(),
vk::pickSubresourceLayers(cDstView->subresources(), 0),
VkOffset3D { 0, 0, 0 },
cDstView->mipLevelExtent(0),
cSrcView->buffer(), 0, 0, 0);
});
}
}
}
void STDMETHODCALLTYPE D3D11DeviceContext::ClearUnorderedAccessViewFloat(
ID3D11UnorderedAccessView* pUnorderedAccessView,
const FLOAT Values[4]) {
D3D10DeviceLock lock = LockContext();
auto uav = static_cast<D3D11UnorderedAccessView*>(pUnorderedAccessView);
if (!uav)
return;
auto imgView = uav->GetImageView();
auto bufView = uav->GetBufferView();
const DxvkFormatInfo* info = nullptr;
if (imgView != nullptr) info = imgView->formatInfo();
if (bufView != nullptr) info = bufView->formatInfo();
if (!info || info->flags.any(DxvkFormatFlag::SampledSInt, DxvkFormatFlag::SampledUInt))
return;
VkClearValue clearValue;
clearValue.color.float32[0] = Values[0];
clearValue.color.float32[1] = Values[1];
clearValue.color.float32[2] = Values[2];
clearValue.color.float32[3] = Values[3];
if (uav->GetResourceType() == D3D11_RESOURCE_DIMENSION_BUFFER) {
EmitCs([
cClearValue = clearValue,
cDstView = std::move(bufView)
] (DxvkContext* ctx) {
ctx->clearBufferView(
cDstView, 0,
cDstView->elementCount(),
cClearValue.color);
});
} else {
EmitCs([
cClearValue = clearValue,
cDstView = std::move(imgView)
] (DxvkContext* ctx) {
ctx->clearImageView(cDstView,
VkOffset3D { 0, 0, 0 },
cDstView->mipLevelExtent(0),
VK_IMAGE_ASPECT_COLOR_BIT,
cClearValue);
});
}
}
void STDMETHODCALLTYPE D3D11DeviceContext::ClearDepthStencilView(
ID3D11DepthStencilView* pDepthStencilView,
UINT ClearFlags,
FLOAT Depth,
UINT8 Stencil) {
D3D10DeviceLock lock = LockContext();
auto dsv = static_cast<D3D11DepthStencilView*>(pDepthStencilView);
if (!dsv)
return;
// Figure out which aspects to clear based on
// the image view properties and clear flags.
VkImageAspectFlags aspectMask = 0;
if (ClearFlags & D3D11_CLEAR_DEPTH)
aspectMask |= VK_IMAGE_ASPECT_DEPTH_BIT;
if (ClearFlags & D3D11_CLEAR_STENCIL)
aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
aspectMask &= dsv->GetWritableAspectMask();
if (!aspectMask)
return;
VkClearValue clearValue;
clearValue.depthStencil.depth = Depth;
clearValue.depthStencil.stencil = Stencil;
EmitCs([
cClearValue = clearValue,
cAspectMask = aspectMask,
cImageView = dsv->GetImageView()
] (DxvkContext* ctx) {
ctx->clearRenderTarget(
cImageView,
cAspectMask,
cClearValue);
});
}
void STDMETHODCALLTYPE D3D11DeviceContext::ClearView(
ID3D11View* pView,
const FLOAT Color[4],
const D3D11_RECT* pRect,
UINT NumRects) {
D3D10DeviceLock lock = LockContext();
if (NumRects && !pRect)
return;
// ID3D11View has no methods to query the exact type of
// the view, so we'll have to check each possible class
auto dsv = dynamic_cast<D3D11DepthStencilView*>(pView);
auto rtv = dynamic_cast<D3D11RenderTargetView*>(pView);
auto uav = dynamic_cast<D3D11UnorderedAccessView*>(pView);
auto vov = dynamic_cast<D3D11VideoProcessorOutputView*>(pView);
// Retrieve underlying resource view
Rc<DxvkBufferView> bufView;
Rc<DxvkImageView> imgView;
if (dsv != nullptr)
imgView = dsv->GetImageView();
if (rtv != nullptr)
imgView = rtv->GetImageView();
if (uav != nullptr) {
bufView = uav->GetBufferView();
imgView = uav->GetImageView();
}
if (vov != nullptr)
imgView = vov->GetView();
// 3D views are unsupported
if (imgView != nullptr
&& imgView->info().type == VK_IMAGE_VIEW_TYPE_3D)
return;
// Query the view format. We'll have to convert
// the clear color based on the format's data type.
VkFormat format = VK_FORMAT_UNDEFINED;
if (bufView != nullptr)
format = bufView->info().format;
if (imgView != nullptr)
format = imgView->info().format;
if (format == VK_FORMAT_UNDEFINED)
return;
// We'll need the format info to determine the buffer
// element size, and we also need it for depth images.
const DxvkFormatInfo* formatInfo = lookupFormatInfo(format);
// Convert the clear color format. ClearView takes
// the clear value for integer formats as a set of
// integral floats, so we'll have to convert.
VkClearValue clearValue = ConvertColorValue(Color, formatInfo);
VkImageAspectFlags clearAspect = formatInfo->aspectMask & (VK_IMAGE_ASPECT_COLOR_BIT | VK_IMAGE_ASPECT_DEPTH_BIT);
// Clear all the rectangles that are specified
for (uint32_t i = 0; i < NumRects || i < 1; i++) {
if (pRect) {
if (pRect[i].left >= pRect[i].right
|| pRect[i].top >= pRect[i].bottom)
continue;
}
if (bufView != nullptr) {
VkDeviceSize offset = 0;
VkDeviceSize length = bufView->info().rangeLength / formatInfo->elementSize;
if (pRect) {
offset = pRect[i].left;
length = pRect[i].right - pRect[i].left;
}
EmitCs([
cBufferView = bufView,
cRangeOffset = offset,
cRangeLength = length,
cClearValue = clearValue
] (DxvkContext* ctx) {
ctx->clearBufferView(
cBufferView,
cRangeOffset,
cRangeLength,
cClearValue.color);
});
}
if (imgView != nullptr) {
VkOffset3D offset = { 0, 0, 0 };
VkExtent3D extent = imgView->mipLevelExtent(0);
if (pRect) {
offset = { pRect[i].left, pRect[i].top, 0 };
extent = {
uint32_t(pRect[i].right - pRect[i].left),
uint32_t(pRect[i].bottom - pRect[i].top), 1 };
}
EmitCs([
cImageView = imgView,
cAreaOffset = offset,
cAreaExtent = extent,
cClearAspect = clearAspect,
cClearValue = clearValue
] (DxvkContext* ctx) {
const VkImageUsageFlags rtUsage =
VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT |
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
bool isFullSize = cImageView->mipLevelExtent(0) == cAreaExtent;
if ((cImageView->info().usage & rtUsage) && isFullSize) {
ctx->clearRenderTarget(
cImageView,
cClearAspect,
cClearValue);
} else {
ctx->clearImageView(
cImageView,
cAreaOffset,
cAreaExtent,
cClearAspect,
cClearValue);
}
});
}
}
}
void STDMETHODCALLTYPE D3D11DeviceContext::GenerateMips(ID3D11ShaderResourceView* pShaderResourceView) {
D3D10DeviceLock lock = LockContext();

View File

@ -58,30 +58,6 @@ namespace dxvk {
ID3D11DeviceChild* pTiledResourceOrViewAccessBeforeBarrier,
ID3D11DeviceChild* pTiledResourceOrViewAccessAfterBarrier);
void STDMETHODCALLTYPE ClearRenderTargetView(
ID3D11RenderTargetView* pRenderTargetView,
const FLOAT ColorRGBA[4]);
void STDMETHODCALLTYPE ClearUnorderedAccessViewUint(
ID3D11UnorderedAccessView* pUnorderedAccessView,
const UINT Values[4]);
void STDMETHODCALLTYPE ClearUnorderedAccessViewFloat(
ID3D11UnorderedAccessView* pUnorderedAccessView,
const FLOAT Values[4]);
void STDMETHODCALLTYPE ClearDepthStencilView(
ID3D11DepthStencilView* pDepthStencilView,
UINT ClearFlags,
FLOAT Depth,
UINT8 Stencil);
void STDMETHODCALLTYPE ClearView(
ID3D11View *pView,
const FLOAT Color[4],
const D3D11_RECT *pRect,
UINT NumRects);
void STDMETHODCALLTYPE GenerateMips(
ID3D11ShaderResourceView* pShaderResourceView);

View File

@ -452,6 +452,432 @@ namespace dxvk {
}
template<typename ContextType>
void STDMETHODCALLTYPE D3D11CommonContext<ContextType>::ClearRenderTargetView(
ID3D11RenderTargetView* pRenderTargetView,
const FLOAT ColorRGBA[4]) {
D3D10DeviceLock lock = LockContext();
auto rtv = static_cast<D3D11RenderTargetView*>(pRenderTargetView);
if (!rtv)
return;
auto view = rtv->GetImageView();
auto color = ConvertColorValue(ColorRGBA, view->formatInfo());
EmitCs([
cClearValue = color,
cImageView = std::move(view)
] (DxvkContext* ctx) {
ctx->clearRenderTarget(
cImageView,
VK_IMAGE_ASPECT_COLOR_BIT,
cClearValue);
});
}
template<typename ContextType>
void STDMETHODCALLTYPE D3D11CommonContext<ContextType>::ClearUnorderedAccessViewUint(
ID3D11UnorderedAccessView* pUnorderedAccessView,
const UINT Values[4]) {
D3D10DeviceLock lock = LockContext();
auto uav = static_cast<D3D11UnorderedAccessView*>(pUnorderedAccessView);
if (!uav)
return;
// Gather UAV format info. We'll use this to determine
// whether we need to create a temporary view or not.
D3D11_UNORDERED_ACCESS_VIEW_DESC uavDesc;
uav->GetDesc(&uavDesc);
VkFormat uavFormat = m_parent->LookupFormat(uavDesc.Format, DXGI_VK_FORMAT_MODE_ANY).Format;
VkFormat rawFormat = m_parent->LookupFormat(uavDesc.Format, DXGI_VK_FORMAT_MODE_RAW).Format;
if (uavFormat != rawFormat && rawFormat == VK_FORMAT_UNDEFINED) {
Logger::err(str::format("D3D11: ClearUnorderedAccessViewUint: No raw format found for ", uavFormat));
return;
}
VkClearValue clearValue;
// R11G11B10 is a special case since there's no corresponding
// integer format with the same bit layout. Use R32 instead.
if (uavFormat == VK_FORMAT_B10G11R11_UFLOAT_PACK32) {
clearValue.color.uint32[0] = ((Values[0] & 0x7FF) << 0)
| ((Values[1] & 0x7FF) << 11)
| ((Values[2] & 0x3FF) << 22);
clearValue.color.uint32[1] = 0;
clearValue.color.uint32[2] = 0;
clearValue.color.uint32[3] = 0;
} else {
clearValue.color.uint32[0] = Values[0];
clearValue.color.uint32[1] = Values[1];
clearValue.color.uint32[2] = Values[2];
clearValue.color.uint32[3] = Values[3];
}
if (uav->GetResourceType() == D3D11_RESOURCE_DIMENSION_BUFFER) {
// In case of raw and structured buffers as well as typed
// buffers that can be used for atomic operations, we can
// use the fast Vulkan buffer clear function.
Rc<DxvkBufferView> bufferView = uav->GetBufferView();
if (bufferView->info().format == VK_FORMAT_R32_UINT
|| bufferView->info().format == VK_FORMAT_R32_SINT
|| bufferView->info().format == VK_FORMAT_R32_SFLOAT
|| bufferView->info().format == VK_FORMAT_B10G11R11_UFLOAT_PACK32) {
EmitCs([
cClearValue = clearValue.color.uint32[0],
cDstSlice = bufferView->slice()
] (DxvkContext* ctx) {
ctx->clearBuffer(
cDstSlice.buffer(),
cDstSlice.offset(),
cDstSlice.length(),
cClearValue);
});
} else {
// Create a view with an integer format if necessary
if (uavFormat != rawFormat) {
DxvkBufferViewCreateInfo info = bufferView->info();
info.format = rawFormat;
bufferView = m_device->createBufferView(
bufferView->buffer(), info);
}
EmitCs([
cClearValue = clearValue,
cDstView = bufferView
] (DxvkContext* ctx) {
ctx->clearBufferView(
cDstView, 0,
cDstView->elementCount(),
cClearValue.color);
});
}
} else {
Rc<DxvkImageView> imageView = uav->GetImageView();
// If the clear value is zero, we can use the original view regardless of
// the format since the bit pattern will not change in any supported format.
bool isZeroClearValue = !(clearValue.color.uint32[0] | clearValue.color.uint32[1]
| clearValue.color.uint32[2] | clearValue.color.uint32[3]);
// Check if we can create an image view with the given raw format. If not,
// we'll have to use a fallback using a texel buffer view and buffer copies.
bool isViewCompatible = uavFormat == rawFormat;
if (!isViewCompatible && (imageView->imageInfo().flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT)) {
uint32_t formatCount = imageView->imageInfo().viewFormatCount;
isViewCompatible = formatCount == 0;
for (uint32_t i = 0; i < formatCount && !isViewCompatible; i++)
isViewCompatible = imageView->imageInfo().viewFormats[i] == rawFormat;
}
if (isViewCompatible || isZeroClearValue) {
// Create a view with an integer format if necessary
if (uavFormat != rawFormat && !isZeroClearValue) {
DxvkImageViewCreateInfo info = imageView->info();
info.format = rawFormat;
imageView = m_device->createImageView(imageView->image(), info);
}
EmitCs([
cClearValue = clearValue,
cDstView = imageView
] (DxvkContext* ctx) {
ctx->clearImageView(cDstView,
VkOffset3D { 0, 0, 0 },
cDstView->mipLevelExtent(0),
VK_IMAGE_ASPECT_COLOR_BIT,
cClearValue);
});
} else {
DxvkBufferCreateInfo bufferInfo;
bufferInfo.size = imageView->formatInfo()->elementSize
* imageView->info().numLayers
* util::flattenImageExtent(imageView->mipLevelExtent(0));
bufferInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT
| VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT;
bufferInfo.stages = VK_PIPELINE_STAGE_TRANSFER_BIT
| VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
bufferInfo.access = VK_ACCESS_TRANSFER_READ_BIT
| VK_ACCESS_SHADER_WRITE_BIT;
Rc<DxvkBuffer> buffer = m_device->createBuffer(bufferInfo,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
DxvkBufferViewCreateInfo bufferViewInfo;
bufferViewInfo.format = rawFormat;
bufferViewInfo.rangeOffset = 0;
bufferViewInfo.rangeLength = bufferInfo.size;
Rc<DxvkBufferView> bufferView = m_device->createBufferView(buffer,
bufferViewInfo);
EmitCs([
cDstView = std::move(imageView),
cSrcView = std::move(bufferView),
cClearValue = clearValue.color
] (DxvkContext* ctx) {
ctx->clearBufferView(
cSrcView, 0,
cSrcView->elementCount(),
cClearValue);
ctx->copyBufferToImage(cDstView->image(),
vk::pickSubresourceLayers(cDstView->subresources(), 0),
VkOffset3D { 0, 0, 0 },
cDstView->mipLevelExtent(0),
cSrcView->buffer(), 0, 0, 0);
});
}
}
}
template<typename ContextType>
void STDMETHODCALLTYPE D3D11CommonContext<ContextType>::ClearUnorderedAccessViewFloat(
ID3D11UnorderedAccessView* pUnorderedAccessView,
const FLOAT Values[4]) {
D3D10DeviceLock lock = LockContext();
auto uav = static_cast<D3D11UnorderedAccessView*>(pUnorderedAccessView);
if (!uav)
return;
auto imgView = uav->GetImageView();
auto bufView = uav->GetBufferView();
const DxvkFormatInfo* info = nullptr;
if (imgView != nullptr) info = imgView->formatInfo();
if (bufView != nullptr) info = bufView->formatInfo();
if (!info || info->flags.any(DxvkFormatFlag::SampledSInt, DxvkFormatFlag::SampledUInt))
return;
VkClearValue clearValue;
clearValue.color.float32[0] = Values[0];
clearValue.color.float32[1] = Values[1];
clearValue.color.float32[2] = Values[2];
clearValue.color.float32[3] = Values[3];
if (uav->GetResourceType() == D3D11_RESOURCE_DIMENSION_BUFFER) {
EmitCs([
cClearValue = clearValue,
cDstView = std::move(bufView)
] (DxvkContext* ctx) {
ctx->clearBufferView(
cDstView, 0,
cDstView->elementCount(),
cClearValue.color);
});
} else {
EmitCs([
cClearValue = clearValue,
cDstView = std::move(imgView)
] (DxvkContext* ctx) {
ctx->clearImageView(cDstView,
VkOffset3D { 0, 0, 0 },
cDstView->mipLevelExtent(0),
VK_IMAGE_ASPECT_COLOR_BIT,
cClearValue);
});
}
}
template<typename ContextType>
void STDMETHODCALLTYPE D3D11CommonContext<ContextType>::ClearDepthStencilView(
ID3D11DepthStencilView* pDepthStencilView,
UINT ClearFlags,
FLOAT Depth,
UINT8 Stencil) {
D3D10DeviceLock lock = LockContext();
auto dsv = static_cast<D3D11DepthStencilView*>(pDepthStencilView);
if (!dsv)
return;
// Figure out which aspects to clear based on
// the image view properties and clear flags.
VkImageAspectFlags aspectMask = 0;
if (ClearFlags & D3D11_CLEAR_DEPTH)
aspectMask |= VK_IMAGE_ASPECT_DEPTH_BIT;
if (ClearFlags & D3D11_CLEAR_STENCIL)
aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
aspectMask &= dsv->GetWritableAspectMask();
if (!aspectMask)
return;
VkClearValue clearValue;
clearValue.depthStencil.depth = Depth;
clearValue.depthStencil.stencil = Stencil;
EmitCs([
cClearValue = clearValue,
cAspectMask = aspectMask,
cImageView = dsv->GetImageView()
] (DxvkContext* ctx) {
ctx->clearRenderTarget(
cImageView,
cAspectMask,
cClearValue);
});
}
template<typename ContextType>
void STDMETHODCALLTYPE D3D11CommonContext<ContextType>::ClearView(
ID3D11View* pView,
const FLOAT Color[4],
const D3D11_RECT* pRect,
UINT NumRects) {
D3D10DeviceLock lock = LockContext();
if (NumRects && !pRect)
return;
// ID3D11View has no methods to query the exact type of
// the view, so we'll have to check each possible class
auto dsv = dynamic_cast<D3D11DepthStencilView*>(pView);
auto rtv = dynamic_cast<D3D11RenderTargetView*>(pView);
auto uav = dynamic_cast<D3D11UnorderedAccessView*>(pView);
auto vov = dynamic_cast<D3D11VideoProcessorOutputView*>(pView);
// Retrieve underlying resource view
Rc<DxvkBufferView> bufView;
Rc<DxvkImageView> imgView;
if (dsv != nullptr)
imgView = dsv->GetImageView();
if (rtv != nullptr)
imgView = rtv->GetImageView();
if (uav != nullptr) {
bufView = uav->GetBufferView();
imgView = uav->GetImageView();
}
if (vov != nullptr)
imgView = vov->GetView();
// 3D views are unsupported
if (imgView != nullptr
&& imgView->info().type == VK_IMAGE_VIEW_TYPE_3D)
return;
// Query the view format. We'll have to convert
// the clear color based on the format's data type.
VkFormat format = VK_FORMAT_UNDEFINED;
if (bufView != nullptr)
format = bufView->info().format;
if (imgView != nullptr)
format = imgView->info().format;
if (format == VK_FORMAT_UNDEFINED)
return;
// We'll need the format info to determine the buffer
// element size, and we also need it for depth images.
const DxvkFormatInfo* formatInfo = lookupFormatInfo(format);
// Convert the clear color format. ClearView takes
// the clear value for integer formats as a set of
// integral floats, so we'll have to convert.
VkClearValue clearValue = ConvertColorValue(Color, formatInfo);
VkImageAspectFlags clearAspect = formatInfo->aspectMask & (VK_IMAGE_ASPECT_COLOR_BIT | VK_IMAGE_ASPECT_DEPTH_BIT);
// Clear all the rectangles that are specified
for (uint32_t i = 0; i < NumRects || i < 1; i++) {
if (pRect) {
if (pRect[i].left >= pRect[i].right
|| pRect[i].top >= pRect[i].bottom)
continue;
}
if (bufView != nullptr) {
VkDeviceSize offset = 0;
VkDeviceSize length = bufView->info().rangeLength / formatInfo->elementSize;
if (pRect) {
offset = pRect[i].left;
length = pRect[i].right - pRect[i].left;
}
EmitCs([
cBufferView = bufView,
cRangeOffset = offset,
cRangeLength = length,
cClearValue = clearValue
] (DxvkContext* ctx) {
ctx->clearBufferView(
cBufferView,
cRangeOffset,
cRangeLength,
cClearValue.color);
});
}
if (imgView != nullptr) {
VkOffset3D offset = { 0, 0, 0 };
VkExtent3D extent = imgView->mipLevelExtent(0);
if (pRect) {
offset = { pRect[i].left, pRect[i].top, 0 };
extent = {
uint32_t(pRect[i].right - pRect[i].left),
uint32_t(pRect[i].bottom - pRect[i].top), 1 };
}
EmitCs([
cImageView = imgView,
cAreaOffset = offset,
cAreaExtent = extent,
cClearAspect = clearAspect,
cClearValue = clearValue
] (DxvkContext* ctx) {
const VkImageUsageFlags rtUsage =
VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT |
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
bool isFullSize = cImageView->mipLevelExtent(0) == cAreaExtent;
if ((cImageView->info().usage & rtUsage) && isFullSize) {
ctx->clearRenderTarget(
cImageView,
cClearAspect,
cClearValue);
} else {
ctx->clearImageView(
cImageView,
cAreaOffset,
cAreaExtent,
cClearAspect,
cClearValue);
}
});
}
}
}
template<typename ContextType>
void STDMETHODCALLTYPE D3D11CommonContext<ContextType>::UpdateSubresource(
ID3D11Resource* pDstResource,

View File

@ -109,6 +109,30 @@ namespace dxvk {
UINT DstAlignedByteOffset,
ID3D11UnorderedAccessView* pSrcView);
void STDMETHODCALLTYPE ClearRenderTargetView(
ID3D11RenderTargetView* pRenderTargetView,
const FLOAT ColorRGBA[4]);
void STDMETHODCALLTYPE ClearUnorderedAccessViewUint(
ID3D11UnorderedAccessView* pUnorderedAccessView,
const UINT Values[4]);
void STDMETHODCALLTYPE ClearUnorderedAccessViewFloat(
ID3D11UnorderedAccessView* pUnorderedAccessView,
const FLOAT Values[4]);
void STDMETHODCALLTYPE ClearDepthStencilView(
ID3D11DepthStencilView* pDepthStencilView,
UINT ClearFlags,
FLOAT Depth,
UINT8 Stencil);
void STDMETHODCALLTYPE ClearView(
ID3D11View *pView,
const FLOAT Color[4],
const D3D11_RECT *pRect,
UINT NumRects);
void STDMETHODCALLTYPE UpdateSubresource(
ID3D11Resource* pDstResource,
UINT DstSubresource,