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:
parent
2740030fca
commit
6d72bc94f4
@ -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,
|
||||
|
@ -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(
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user