1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-01-29 17:52:18 +01:00

[d3d11] Allow creation of shader resource views for planar images

This commit is contained in:
Philip Rebohle 2021-05-20 16:50:15 +02:00
parent 2740030fca
commit 6d72bc94f4
No known key found for this signature in database
GPG Key ID: C8CC613427A31C99
8 changed files with 111 additions and 36 deletions

View File

@ -299,8 +299,10 @@ namespace dxvk {
ID3D11ShaderResourceView** ppSRView) {
InitReturnPtr(ppSRView);
uint32_t plane = GetViewPlaneIndex(pResource, pDesc ? pDesc->Format : DXGI_FORMAT_UNKNOWN);
D3D11_SHADER_RESOURCE_VIEW_DESC1 desc = pDesc
? D3D11ShaderResourceView::PromoteDesc(pDesc)
? D3D11ShaderResourceView::PromoteDesc(pDesc, plane)
: D3D11_SHADER_RESOURCE_VIEW_DESC1();
ID3D11ShaderResourceView1* view = nullptr;
@ -342,13 +344,16 @@ namespace dxvk {
if (FAILED(D3D11ShaderResourceView::NormalizeDesc(pResource, &desc)))
return E_INVALIDARG;
}
uint32_t plane = D3D11ShaderResourceView::GetPlaneSlice(&desc);
if (!CheckResourceViewCompatibility(pResource, D3D11_BIND_SHADER_RESOURCE, desc.Format)) {
if (!CheckResourceViewCompatibility(pResource, D3D11_BIND_SHADER_RESOURCE, desc.Format, plane)) {
Logger::err(str::format("D3D11: Cannot create shader resource view:",
"\n Resource type: ", resourceDesc.Dim,
"\n Resource usage: ", resourceDesc.BindFlags,
"\n Resource format: ", resourceDesc.Format,
"\n View format: ", desc.Format));
"\n View format: ", desc.Format,
"\n View plane: ", plane));
return E_INVALIDARG;
}
@ -415,7 +420,7 @@ namespace dxvk {
return E_INVALIDARG;
}
if (!CheckResourceViewCompatibility(pResource, D3D11_BIND_UNORDERED_ACCESS, desc.Format)) {
if (!CheckResourceViewCompatibility(pResource, D3D11_BIND_UNORDERED_ACCESS, desc.Format, 0)) {
Logger::err(str::format("D3D11: Cannot create unordered access view:",
"\n Resource type: ", resourceDesc.Dim,
"\n Resource usage: ", resourceDesc.BindFlags,
@ -495,7 +500,7 @@ namespace dxvk {
return E_INVALIDARG;
}
if (!CheckResourceViewCompatibility(pResource, D3D11_BIND_RENDER_TARGET, desc.Format)) {
if (!CheckResourceViewCompatibility(pResource, D3D11_BIND_RENDER_TARGET, desc.Format, 0)) {
Logger::err(str::format("D3D11: Cannot create render target view:",
"\n Resource type: ", resourceDesc.Dim,
"\n Resource usage: ", resourceDesc.BindFlags,
@ -543,7 +548,7 @@ namespace dxvk {
return E_INVALIDARG;
}
if (!CheckResourceViewCompatibility(pResource, D3D11_BIND_DEPTH_STENCIL, desc.Format)) {
if (!CheckResourceViewCompatibility(pResource, D3D11_BIND_DEPTH_STENCIL, desc.Format, 0)) {
Logger::err(str::format("D3D11: Cannot create depth-stencil view:",
"\n Resource type: ", resourceDesc.Dim,
"\n Resource usage: ", resourceDesc.BindFlags,
@ -2219,6 +2224,32 @@ namespace dxvk {
}
uint32_t D3D11Device::GetViewPlaneIndex(
ID3D11Resource* pResource,
DXGI_FORMAT ViewFormat) {
auto texture = GetCommonTexture(pResource);
if (!texture)
return 0;
uint32_t planeCount = texture->GetPlaneCount();
if (planeCount == 1)
return 0;
auto formatMode = texture->GetFormatMode();
auto formatFamily = LookupFamily(texture->Desc()->Format, formatMode);
auto viewFormat = LookupFormat(ViewFormat, formatMode);
for (uint32_t i = 0; i < formatFamily.FormatCount; i++) {
if (formatFamily.Formats[i] == viewFormat.Format)
return i % planeCount;
}
return ~0u;
}
template<typename Void>
void D3D11Device::CopySubresourceData(
Void* pData,

View File

@ -471,6 +471,10 @@ namespace dxvk {
BOOL GetImageTypeSupport(
VkFormat Format,
VkImageType Type) const;
uint32_t GetViewPlaneIndex(
ID3D11Resource* pResource,
DXGI_FORMAT ViewFormat);
template<typename Void>
void CopySubresourceData(

View File

@ -187,12 +187,13 @@ namespace dxvk {
BOOL CheckResourceViewCompatibility(
ID3D11Resource* pResource,
UINT BindFlags,
DXGI_FORMAT Format) {
DXGI_FORMAT Format,
UINT Plane) {
auto texture = GetCommonTexture(pResource);
auto buffer = GetCommonBuffer (pResource);
return texture != nullptr
? texture->CheckViewCompatibility(BindFlags, Format)
? texture->CheckViewCompatibility(BindFlags, Format, Plane)
: buffer ->CheckViewCompatibility(BindFlags, Format);
}

View File

@ -111,13 +111,16 @@ namespace dxvk {
* texture, certain restrictions apply on which formats
* can be used to view the resource.
* \param [in] pResource The resource to check
* \param [in] BindFlags Bind flags required for the view
* \param [in] Format The desired view format
* \param [in] Plane Plane slice for planar formats
* \returns \c true if the format is compatible
*/
BOOL CheckResourceViewCompatibility(
ID3D11Resource* pResource,
UINT BindFlags,
DXGI_FORMAT Format);
DXGI_FORMAT Format,
UINT Plane);
/**
* \brief Increments private reference count of a resource

View File

@ -294,7 +294,12 @@ namespace dxvk {
}
bool D3D11CommonTexture::CheckViewCompatibility(UINT BindFlags, DXGI_FORMAT Format) const {
uint32_t D3D11CommonTexture::GetPlaneCount() const {
return vk::getPlaneCount(m_image->formatInfo()->aspectMask);
}
bool D3D11CommonTexture::CheckViewCompatibility(UINT BindFlags, DXGI_FORMAT Format, UINT Plane) const {
const DxvkImageCreateInfo& imageInfo = m_image->info();
// Check whether the given bind flags are supported
@ -306,6 +311,12 @@ namespace dxvk {
DXGI_VK_FORMAT_INFO viewFormat = m_device->LookupFormat(Format, formatMode);
DXGI_VK_FORMAT_INFO baseFormat = m_device->LookupFormat(m_desc.Format, formatMode);
// Check whether the plane index is valid for the given format
uint32_t planeCount = GetPlaneCount();
if (Plane >= planeCount)
return false;
if (imageInfo.flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT) {
// Check whether the given combination of image
// view type and view format is actually supported
@ -314,19 +325,21 @@ namespace dxvk {
if (!CheckFormatFeatureSupport(viewFormat.Format, features))
return false;
// Using the image format itself is always legal
if (viewFormat.Format == baseFormat.Format)
// Using the image format itself is supported for non-planar formats
if (viewFormat.Format == baseFormat.Format && planeCount == 1)
return true;
// If there is a list of compatible formats, the
// view format must be included in that list.
for (size_t i = 0; i < imageInfo.viewFormatCount; i++) {
if (imageInfo.viewFormats[i] == viewFormat.Format)
// If there is a list of compatible formats, the view format must be
// included in that list. For planar formats, the list is laid out in
// such a way that the n-th format is supported for the n-th plane.
for (size_t i = Plane; i < imageInfo.viewFormatCount; i += planeCount) {
if (imageInfo.viewFormats[i] == viewFormat.Format) {
return true;
}
}
// Otherwise, all bit-compatible formats can be used.
if (imageInfo.viewFormatCount == 0) {
if (imageInfo.viewFormatCount == 0 && planeCount == 1) {
auto baseFormatInfo = imageFormatInfo(baseFormat.Format);
auto viewFormatInfo = imageFormatInfo(viewFormat.Format);
@ -338,7 +351,7 @@ namespace dxvk {
} else {
// For non-mutable images, the view format
// must be identical to the image format.
return viewFormat.Format == baseFormat.Format;
return viewFormat.Format == baseFormat.Format && planeCount == 1;
}
}

View File

@ -206,7 +206,15 @@ namespace dxvk {
* \returns Format mode
*/
DXGI_VK_FORMAT_MODE GetFormatMode() const;
/**
* \brief Computes plane count
*
* For non-planar formats, the plane count will be 1.
* \returns Image plane count
*/
uint32_t GetPlaneCount() const;
/**
* \brief Checks whether a view can be created for this textue
*
@ -216,11 +224,13 @@ namespace dxvk {
* will also check whether the required bind flags are supported.
* \param [in] BindFlags Bind flags for the view
* \param [in] Format The desired view format
* \param [in] Plane Plane slice for planar formats
* \returns \c true if the format is compatible
*/
bool CheckViewCompatibility(
UINT BindFlags,
DXGI_FORMAT Format) const;
DXGI_FORMAT Format,
UINT Plane) const;
/**
* \brief Normalizes and validates texture description

View File

@ -71,15 +71,15 @@ namespace dxvk {
m_bufferView = pDevice->GetDXVKDevice()->createBufferView(
buffer->GetBuffer(), viewInfo);
} else {
const DXGI_VK_FORMAT_INFO formatInfo = pDevice->LookupFormat(
pDesc->Format, GetCommonTexture(pResource)->GetFormatMode());
auto texture = GetCommonTexture(pResource);
auto formatInfo = pDevice->LookupFormat(pDesc->Format, texture->GetFormatMode());
DxvkImageViewCreateInfo viewInfo;
viewInfo.format = formatInfo.Format;
viewInfo.aspect = formatInfo.Aspect;
viewInfo.swizzle = formatInfo.Swizzle;
viewInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT;
// Shaders expect the stencil value in the G component
if (viewInfo.aspect == VK_IMAGE_ASPECT_STENCIL_BIT) {
viewInfo.swizzle = VkComponentMapping {
@ -164,6 +164,9 @@ namespace dxvk {
throw DxvkError("D3D11: Invalid view dimension for image SRV");
}
if (texture->GetPlaneCount() > 1)
viewInfo.aspect = vk::getPlaneAspect(GetPlaneSlice(pDesc));
// Populate view info struct
m_info.Image.Aspects = viewInfo.aspect;
m_info.Image.MinLevel = viewInfo.minLevel;
@ -172,8 +175,7 @@ namespace dxvk {
m_info.Image.NumLayers = viewInfo.numLayers;
// Create the underlying image view object
m_imageView = pDevice->GetDXVKDevice()->createImageView(
GetCommonTexture(pResource)->GetImage(), viewInfo);
m_imageView = pDevice->GetDXVKDevice()->createImageView(texture->GetImage(), viewInfo);
}
}
@ -371,7 +373,8 @@ namespace dxvk {
D3D11_SHADER_RESOURCE_VIEW_DESC1 D3D11ShaderResourceView::PromoteDesc(
const D3D11_SHADER_RESOURCE_VIEW_DESC* pDesc) {
const D3D11_SHADER_RESOURCE_VIEW_DESC* pDesc,
UINT Plane) {
D3D11_SHADER_RESOURCE_VIEW_DESC1 dstDesc;
dstDesc.Format = pDesc->Format;
dstDesc.ViewDimension = pDesc->ViewDimension;
@ -395,7 +398,7 @@ namespace dxvk {
case D3D11_SRV_DIMENSION_TEXTURE2D:
dstDesc.Texture2D.MostDetailedMip = pDesc->Texture2D.MostDetailedMip;
dstDesc.Texture2D.MipLevels = pDesc->Texture2D.MipLevels;
dstDesc.Texture2D.PlaneSlice = 0;
dstDesc.Texture2D.PlaneSlice = Plane;
break;
case D3D11_SRV_DIMENSION_TEXTURE2DARRAY:
@ -403,7 +406,7 @@ namespace dxvk {
dstDesc.Texture2DArray.MipLevels = pDesc->Texture2DArray.MipLevels;
dstDesc.Texture2DArray.FirstArraySlice = pDesc->Texture2DArray.FirstArraySlice;
dstDesc.Texture2DArray.ArraySize = pDesc->Texture2DArray.ArraySize;
dstDesc.Texture2DArray.PlaneSlice = 0;
dstDesc.Texture2DArray.PlaneSlice = Plane;
break;
case D3D11_SRV_DIMENSION_TEXTURE2DMS:
@ -535,9 +538,6 @@ namespace dxvk {
case D3D11_SRV_DIMENSION_TEXTURE2D:
if (pDesc->Texture2D.MipLevels > mipLevels - pDesc->Texture2D.MostDetailedMip)
pDesc->Texture2D.MipLevels = mipLevels - pDesc->Texture2D.MostDetailedMip;
if (pDesc->Texture2D.PlaneSlice != 0)
return E_INVALIDARG;
break;
case D3D11_SRV_DIMENSION_TEXTURE2DARRAY:
@ -545,9 +545,6 @@ namespace dxvk {
pDesc->Texture2DArray.MipLevels = mipLevels - pDesc->Texture2DArray.MostDetailedMip;
if (pDesc->Texture2DArray.ArraySize > numLayers - pDesc->Texture2DArray.FirstArraySlice)
pDesc->Texture2DArray.ArraySize = numLayers - pDesc->Texture2DArray.FirstArraySlice;
if (pDesc->Texture2DArray.PlaneSlice != 0)
return E_INVALIDARG;
break;
case D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY:
@ -579,4 +576,16 @@ namespace dxvk {
return S_OK;
}
UINT D3D11ShaderResourceView::GetPlaneSlice(const D3D11_SHADER_RESOURCE_VIEW_DESC1* pDesc) {
switch (pDesc->ViewDimension) {
case D3D11_SRV_DIMENSION_TEXTURE2D:
return pDesc->Texture2D.PlaneSlice;
case D3D11_SRV_DIMENSION_TEXTURE2DARRAY:
return pDesc->Texture2DArray.PlaneSlice;
default:
return 0;
}
}
}

View File

@ -70,12 +70,16 @@ namespace dxvk {
D3D11_SHADER_RESOURCE_VIEW_DESC1* pDesc);
static D3D11_SHADER_RESOURCE_VIEW_DESC1 PromoteDesc(
const D3D11_SHADER_RESOURCE_VIEW_DESC* pDesc);
const D3D11_SHADER_RESOURCE_VIEW_DESC* pDesc,
UINT Plane);
static HRESULT NormalizeDesc(
ID3D11Resource* pResource,
D3D11_SHADER_RESOURCE_VIEW_DESC1* pDesc);
static UINT GetPlaneSlice(
const D3D11_SHADER_RESOURCE_VIEW_DESC1* pDesc);
private:
ID3D11Resource* m_resource;