mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-02-20 19:54:19 +01:00
[d3d11] Move Clear* methods to D3D11CommonContext
This commit is contained in:
parent
50942cd2d9
commit
751d7467df
@ -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();
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
Loading…
x
Reference in New Issue
Block a user