You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1141 lines
46 KiB
C++
1141 lines
46 KiB
C++
/*
|
|
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
|
* its licensors.
|
|
*
|
|
* For complete copyright and license terms please see the LICENSE at the root of this
|
|
* distribution (the "License"). All use of this software is governed by the License,
|
|
* or, if provided, by the license below or the license accompanying this file. Do not
|
|
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
*
|
|
*/
|
|
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
|
|
|
// Description : Implements the resource view related functions
|
|
|
|
|
|
#include "RenderDll_precompiled.h"
|
|
|
|
#include "GLView.hpp"
|
|
#include "GLDevice.hpp"
|
|
|
|
namespace NCryOpenGL
|
|
{
|
|
CResourceName CreateTextureView(STexture* pTexture, const SGIFormatInfo* pFormatInfo, GLenum eTarget, GLuint uMinMipLevel, GLuint uNumMipLevels, GLuint uMinLayer, GLuint uNumLayers, CContext* pContext)
|
|
{
|
|
#if DXGL_SUPPORT_TEXTURE_VIEWS
|
|
if (pContext->GetDevice()->IsFeatureSupported(eF_TextureViews))
|
|
{
|
|
GLint iInternalFormat;
|
|
if (pFormatInfo->m_eTypelessConversion != eGIFC_TEXTURE_VIEW)
|
|
{
|
|
// This can happen if lazy texture view creation is disabled or two views with different modifiers
|
|
// are bound at the same time (for example one view as DEPTH_TO_RED, one as STENCIL_TO_GREEN).
|
|
// In this case create a view with same format as the original texture, so that it will have its own
|
|
// separate format modifier.
|
|
iInternalFormat = GetGIFormatInfo(pTexture->m_eFormat)->m_pTexture->m_iInternalFormat;
|
|
}
|
|
else
|
|
{
|
|
if (pFormatInfo->m_pTexture == NULL)
|
|
{
|
|
DXGL_ERROR("Invalid format for texture view");
|
|
return CResourceName();
|
|
}
|
|
|
|
iInternalFormat = pFormatInfo->m_pTexture->m_iInternalFormat;
|
|
}
|
|
|
|
GLuint uView;
|
|
glGenTextures(1, &uView);
|
|
glTextureViewEXT(uView, eTarget, pTexture->m_kName.GetName(), iInternalFormat, uMinMipLevel, uNumMipLevels, uMinLayer, uNumLayers);
|
|
return pContext->GetDevice()->GetTextureNamePool().Create(uView);
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
DXGL_ERROR("glTextureView not supported - cannot create the requested unique view for the texture");
|
|
return CResourceName();
|
|
}
|
|
}
|
|
|
|
CResourceName CreateTextureBuffer(SBuffer* pBuffer, const SGIFormatInfo* pFormatInfo, uint32 uFirstElement, uint32 uNumElements, CContext* pContext)
|
|
{
|
|
#if DXGL_SUPPORT_TEXTURE_BUFFERS
|
|
uint32 uElementSize(pFormatInfo->m_pTexture->m_uNumBlockBytes);
|
|
uint32 uViewSize(uNumElements * uElementSize);
|
|
bool bEntireBuffer(uFirstElement == 0 && uViewSize == pBuffer->m_uSize);
|
|
|
|
#if !defined(glTexBufferRange)
|
|
if (!bEntireBuffer)
|
|
{
|
|
DXGL_ERROR("glTexBufferRange is not supported - can't create an arbitrary texture buffer");
|
|
return CResourceName();
|
|
}
|
|
#endif //!defined(glTexBufferRange)
|
|
|
|
GLuint uView;
|
|
glGenTextures(1, &uView);
|
|
|
|
#if defined(glTexBufferRange)
|
|
if (!bEntireBuffer)
|
|
{
|
|
glTextureBufferRangeEXT(uView, GL_TEXTURE_BUFFER, pFormatInfo->m_pTexture->m_iInternalFormat, pBuffer->m_kName.GetName(), uFirstElement * uElementSize, uViewSize);
|
|
}
|
|
else
|
|
#endif //defined(glTexBufferRange)
|
|
glTextureBufferEXT(uView, GL_TEXTURE_BUFFER, pFormatInfo->m_pTexture->m_iInternalFormat, pBuffer->m_kName.GetName());
|
|
|
|
return pContext->GetDevice()->GetTextureNamePool().Create(uView);
|
|
#else
|
|
DXGL_ERROR("Buffer shader resource views are not supported on this configuration");
|
|
return CResourceName();
|
|
#endif
|
|
}
|
|
|
|
SShaderView::SShaderView(Type eType)
|
|
: m_eType(eType)
|
|
{
|
|
}
|
|
|
|
SShaderView::~SShaderView()
|
|
{
|
|
}
|
|
|
|
SShaderBufferView::SShaderBufferView(const SBufferRange& kRange)
|
|
: SShaderView(eSVT_Buffer)
|
|
, m_kRange(kRange)
|
|
{
|
|
}
|
|
|
|
SShaderBufferView::~SShaderBufferView()
|
|
{
|
|
}
|
|
|
|
void SShaderBufferView::Init(SBuffer* pBuffer, CContext* pContext)
|
|
{
|
|
pBuffer->m_kCreationFence.IssueWait(pContext);
|
|
m_kName = pBuffer->m_kName;
|
|
m_kCreationFence.IssueFence(pContext->GetDevice());
|
|
}
|
|
|
|
SShaderTextureBasedView::SShaderTextureBasedView(Type eType)
|
|
: SShaderView(eType)
|
|
, m_bTextureOwned(false)
|
|
{
|
|
}
|
|
|
|
SShaderTextureBasedView::~SShaderTextureBasedView()
|
|
{
|
|
if (m_bTextureOwned)
|
|
{
|
|
GLuint uTextureName(m_kName.GetName());
|
|
glDeleteTextures(1, &uTextureName);
|
|
}
|
|
}
|
|
|
|
bool SShaderTextureBasedView::BindTextureUnit(SSamplerState* pSamplerState, STextureUnitContext& kContext, CContext* pContext, const STextureUnitCache& kCurrentUnitCache)
|
|
{
|
|
DXGL_ERROR("Cannot bind this type of texture based view to a texture unit");
|
|
return false;
|
|
}
|
|
|
|
bool SShaderTextureBasedView::GenerateMipmaps(CContext*)
|
|
{
|
|
DXGL_ERROR("Cannot create mipmaps from this type of texture based view");
|
|
return false;
|
|
}
|
|
|
|
SShaderTextureBufferView::SShaderTextureBufferView(const SShaderTextureBufferViewConfiguration& kConfiguration)
|
|
: SShaderTextureBasedView(eSVT_Texture)
|
|
, m_pBuffer(NULL)
|
|
, m_kConfiguration(kConfiguration)
|
|
, m_pNextView(NULL)
|
|
{
|
|
}
|
|
|
|
SShaderTextureBufferView::~SShaderTextureBufferView()
|
|
{
|
|
if (m_pBuffer != NULL)
|
|
{
|
|
SShaderTextureBufferView** pLink = &m_pBuffer->m_pTextureBuffersHead;
|
|
while (*pLink != NULL)
|
|
{
|
|
if (*pLink == this)
|
|
{
|
|
*pLink = m_pNextView;
|
|
break;
|
|
}
|
|
pLink = &((*pLink)->m_pNextView);
|
|
}
|
|
}
|
|
}
|
|
|
|
bool SShaderTextureBufferView::Init(SBuffer* pBuffer, CContext* pContext)
|
|
{
|
|
const SGIFormatInfo* pFormatInfo;
|
|
if ((pFormatInfo = GetGIFormatInfo(m_kConfiguration.m_eFormat)) == NULL ||
|
|
pFormatInfo->m_pTexture == NULL)
|
|
{
|
|
DXGL_ERROR("Invalid format for buffer view");
|
|
return false;
|
|
}
|
|
|
|
pBuffer->m_kCreationFence.IssueWait(pContext);
|
|
|
|
CResourceName kTextureBufferName(CreateTextureBuffer(pBuffer, pFormatInfo, m_kConfiguration.m_uFirstElement, m_kConfiguration.m_uNumElements, pContext));
|
|
if (!kTextureBufferName.IsValid())
|
|
{
|
|
return false;
|
|
}
|
|
|
|
m_kName = kTextureBufferName;
|
|
m_kCreationFence.IssueFence(pContext->GetDevice());
|
|
m_bTextureOwned = true;
|
|
|
|
m_pBuffer = pBuffer;
|
|
m_pNextView = pBuffer->m_pTextureBuffersHead;
|
|
pBuffer->m_pTextureBuffersHead = this;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool SShaderTextureBufferView::BindTextureUnit(SSamplerState* pSamplerState, STextureUnitContext& kContext, CContext* pContext, const STextureUnitCache& kCurrentUnitCache)
|
|
{
|
|
kContext.m_kCurrentUnitState.m_kTextureName = m_kName;
|
|
kContext.m_kCurrentUnitState.m_uSampler = pSamplerState->m_uSamplerObjectNoMip;
|
|
#if DXGLES
|
|
// OpenGL ES does not have texture buffers
|
|
DXGL_TODO("Find alternatives for TEXTURE BUFFER")
|
|
kContext.m_kCurrentUnitState.m_eTextureTarget = GL_INVALID_ENUM;
|
|
#else
|
|
kContext.m_kCurrentUnitState.m_eTextureTarget = GL_TEXTURE_BUFFER;
|
|
#endif
|
|
assert(m_kName.IsValid());
|
|
return true;
|
|
}
|
|
|
|
SShaderTextureView::SShaderTextureView(const SShaderTextureViewConfiguration& kConfiguration)
|
|
: SShaderTextureBasedView(eSVT_Texture)
|
|
, m_pTexture(NULL)
|
|
, m_kConfiguration(kConfiguration)
|
|
, m_pNextView(NULL)
|
|
{
|
|
}
|
|
|
|
SShaderTextureView::~SShaderTextureView()
|
|
{
|
|
if (m_pTexture != NULL)
|
|
{
|
|
SShaderTextureView** pLink = &m_pTexture->m_pShaderViewsHead;
|
|
while (*pLink != NULL)
|
|
{
|
|
if (*pLink == this)
|
|
{
|
|
*pLink = m_pNextView;
|
|
break;
|
|
}
|
|
pLink = &((*pLink)->m_pNextView);
|
|
}
|
|
}
|
|
}
|
|
|
|
bool SShaderTextureView::Init(STexture* pTexture, CContext* pContext)
|
|
{
|
|
const SGIFormatInfo* pFormatInfo;
|
|
if (m_kConfiguration.m_eFormat == eGIF_NUM ||
|
|
(pFormatInfo = GetGIFormatInfo(m_kConfiguration.m_eFormat)) == NULL)
|
|
{
|
|
DXGL_ERROR("Invalid format for shader resource view");
|
|
return false;
|
|
}
|
|
|
|
m_kViewState.m_iBaseMipLevel = (GLint)m_kConfiguration.m_uMinMipLevel;
|
|
m_kViewState.m_iMaxMipLevel = (GLint)(m_kConfiguration.m_uMinMipLevel + m_kConfiguration.m_uNumMipLevels - 1);
|
|
m_kViewState.m_uSwizzleMask = pFormatInfo->m_uDXGISwizzleMask;
|
|
#if DXGL_SUPPORT_STENCIL_TEXTURES
|
|
m_kViewState.m_iDepthStencilTextureMode = 0;
|
|
#endif //DXGL_SUPPORT_STENCIL_TEXTURES
|
|
m_pTexture = pTexture;
|
|
|
|
m_bFormatRequiresUniqueView = false;
|
|
if (m_kConfiguration.m_eFormat != pTexture->m_eFormat)
|
|
{
|
|
if (pFormatInfo->m_eTypelessFormat != pTexture->m_eFormat)
|
|
{
|
|
DXGL_ERROR("Shader resource view format is not compatible with texture format");
|
|
return false;
|
|
}
|
|
|
|
switch (pFormatInfo->m_eTypelessConversion)
|
|
{
|
|
case eGIFC_DEPTH_TO_RED:
|
|
#if DXGL_SUPPORT_STENCIL_TEXTURES
|
|
if (pContext->GetDevice()->IsFeatureSupported(eF_StencilTextures))
|
|
{
|
|
m_kViewState.m_iDepthStencilTextureMode = GL_DEPTH_COMPONENT;
|
|
}
|
|
#endif //DXGL_SUPPORT_STENCIL_TEXTURES
|
|
break;
|
|
case eGIFC_STENCIL_TO_RED:
|
|
#if DXGL_SUPPORT_STENCIL_TEXTURES
|
|
if (pContext->GetDevice()->IsFeatureSupported(eF_StencilTextures))
|
|
{
|
|
m_kViewState.m_iDepthStencilTextureMode = GL_STENCIL_INDEX;
|
|
}
|
|
else
|
|
#endif //DXGL_SUPPORT_STENCIL_TEXTURES
|
|
{
|
|
DXGL_ERROR("Stencil texturing not supported - cannot create shader resource view for stencil format");
|
|
return false;
|
|
}
|
|
break;
|
|
case eGIFC_TEXTURE_VIEW:
|
|
m_bFormatRequiresUniqueView = true;
|
|
break;
|
|
case eGIFC_UNSUPPORTED:
|
|
DXGL_ERROR("Shader resource view conversion not supported for the requested format");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if (m_kConfiguration.m_eTarget != pTexture->m_eTarget)
|
|
{
|
|
m_bFormatRequiresUniqueView = true;
|
|
}
|
|
|
|
if (m_bFormatRequiresUniqueView ||
|
|
m_kConfiguration.m_uMinLayer > 0 ||
|
|
m_kConfiguration.m_uNumLayers != pTexture->m_uNumElements)
|
|
{
|
|
if (!CreateUniqueView(pContext))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_kName = pTexture->m_kName;
|
|
pTexture->m_kCreationFence.IssueWait(pContext);
|
|
m_kCreationFence.IssueFence(pContext->GetDevice());
|
|
m_bTextureOwned = false;
|
|
}
|
|
|
|
m_pNextView = pTexture->m_pShaderViewsHead;
|
|
pTexture->m_pShaderViewsHead = this;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool SShaderTextureView::CreateUniqueView(CContext* pContext)
|
|
{
|
|
const SGIFormatInfo* pFormatInfo(GetGIFormatInfo(m_kConfiguration.m_eFormat));
|
|
|
|
m_pTexture->m_kCreationFence.IssueWait(pContext);
|
|
|
|
CResourceName kUniqueView = CreateTextureView(
|
|
m_pTexture, pFormatInfo, m_kConfiguration.m_eTarget,
|
|
m_kConfiguration.m_uMinMipLevel, m_kConfiguration.m_uNumMipLevels,
|
|
m_kConfiguration.m_uMinLayer, m_kConfiguration.m_uNumLayers,
|
|
pContext);
|
|
|
|
if (kUniqueView.IsValid())
|
|
{
|
|
m_kName = kUniqueView;
|
|
m_bTextureOwned = true;
|
|
|
|
m_kViewState.ApplyFormatMode(kUniqueView.GetName(), m_kConfiguration.m_eTarget);
|
|
m_kCreationFence.IssueFence(pContext->GetDevice());
|
|
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool SShaderTextureView::BindTextureUnit(SSamplerState* pSamplerState, STextureUnitContext& kContext, CContext* pContext, const STextureUnitCache& kCurrentUnitCache)
|
|
{
|
|
kContext.m_kCurrentUnitState.m_uSampler = m_kConfiguration.m_uNumMipLevels > 1 ?
|
|
pSamplerState->m_uSamplerObjectMip :
|
|
pSamplerState->m_uSamplerObjectNoMip;
|
|
kContext.m_kCurrentUnitState.m_eTextureTarget = m_kConfiguration.m_eTarget;
|
|
|
|
if (!m_bTextureOwned)
|
|
{
|
|
if (m_kConfiguration.m_eTarget == m_pTexture->m_eTarget)
|
|
{
|
|
if (m_pTexture->m_pBoundModifier == this)
|
|
{
|
|
kContext.m_kCurrentUnitState.m_kTextureName = m_pTexture->m_kName;
|
|
return true;
|
|
}
|
|
|
|
if (m_pTexture->m_pBoundModifier == NULL || (m_pTexture->m_pBoundModifier && !m_bFormatRequiresUniqueView))
|
|
{
|
|
if (m_pTexture->m_kCache != m_kViewState)
|
|
{
|
|
m_kViewState.Apply(m_pTexture->m_kName.GetName(), m_kConfiguration.m_eTarget, kCurrentUnitCache);
|
|
m_pTexture->m_kCache = m_kViewState;
|
|
}
|
|
m_pTexture->m_pBoundModifier = this;
|
|
kContext.m_kModifiedTextures.push_back(m_pTexture);
|
|
kContext.m_kCurrentUnitState.m_kTextureName = m_pTexture->m_kName;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
if (!CreateUniqueView(pContext))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
kContext.m_kCurrentUnitState.m_kTextureName = m_kName;
|
|
return true;
|
|
}
|
|
|
|
bool SShaderTextureView::GenerateMipmaps(CContext* pContext)
|
|
{
|
|
DXGL_TODO("Verify the expected behavior when the view has non-default parameters (currently ignored)")
|
|
glGenerateTextureMipmapEXT(m_pTexture->m_kName.GetName(), m_kConfiguration.m_eTarget);
|
|
m_kCreationFence.IssueWait(pContext);
|
|
return true;
|
|
}
|
|
|
|
SShaderImageView::SShaderImageView(const SShaderImageViewConfiguration& kConfiguration)
|
|
: SShaderTextureBasedView(eSVT_Image)
|
|
, m_kConfiguration(kConfiguration)
|
|
{
|
|
}
|
|
|
|
SShaderImageView::~SShaderImageView()
|
|
{
|
|
}
|
|
|
|
bool SShaderImageView::Init(STexture* pTexture, CContext* pContext)
|
|
{
|
|
m_kName = pTexture->m_kName;
|
|
pTexture->m_kCreationFence.IssueWait(pContext);
|
|
m_kCreationFence.IssueFence(pContext->GetDevice());
|
|
m_bTextureOwned = false;
|
|
return true;
|
|
}
|
|
|
|
bool SShaderImageView::Init(SShaderTextureBasedView* pTextureBufferView, CContext* pContext)
|
|
{
|
|
m_spAuxiliaryView = pTextureBufferView;
|
|
m_kName = pTextureBufferView->m_kName;
|
|
pTextureBufferView->m_kCreationFence.IssueWait(pContext);
|
|
m_kCreationFence.IssueFence(pContext->GetDevice());
|
|
m_bTextureOwned = false;
|
|
return true;
|
|
}
|
|
|
|
SOutputMergerView::SOutputMergerView(const CResourceName& kUniqueView, EGIFormat eFormat)
|
|
: m_kUniqueView(kUniqueView)
|
|
, m_eFormat(eFormat)
|
|
{
|
|
memset(m_kContextMap, 0, sizeof(m_kContextMap));
|
|
}
|
|
|
|
SOutputMergerView::~SOutputMergerView()
|
|
{
|
|
uint32 uContext;
|
|
for (uContext = 0; uContext < DXGL_ARRAY_SIZE(m_kContextMap); ++uContext)
|
|
{
|
|
SContextData* pContextData(m_kContextMap[uContext]);
|
|
if (pContextData != NULL)
|
|
{
|
|
// All frame buffers with this view bound must be removed from the cache and deleted
|
|
TFrameBufferRefs::iterator kFrameBufferRefIter(pContextData->m_kBoundFrameBuffers.begin());
|
|
const TFrameBufferRefs::iterator kFrameBufferRefEnd(pContextData->m_kBoundFrameBuffers.end());
|
|
while (kFrameBufferRefIter != kFrameBufferRefEnd)
|
|
{
|
|
SFrameBuffer* pFrameBuffer(kFrameBufferRefIter->m_spFrameBuffer);
|
|
pFrameBuffer->m_pContext->RemoveFrameBuffer(pFrameBuffer, this);
|
|
++kFrameBufferRefIter;
|
|
}
|
|
|
|
delete pContextData;
|
|
}
|
|
}
|
|
|
|
if (m_kUniqueView.IsValid())
|
|
{
|
|
GLuint uUniqueViewName(m_kUniqueView.GetName());
|
|
glDeleteTextures(1, &uUniqueViewName);
|
|
}
|
|
}
|
|
|
|
bool SOutputMergerView::AttachFrameBuffer(SFrameBuffer* pFrameBuffer, GLenum eAttachmentID, CContext* pContext)
|
|
{
|
|
SContextData* pContextData(m_kContextMap[pFrameBuffer->m_pContext->GetIndex()]);
|
|
if (pContextData == NULL)
|
|
{
|
|
pContextData = new SContextData();
|
|
m_kContextMap[pFrameBuffer->m_pContext->GetIndex()] = pContextData;
|
|
}
|
|
|
|
TFrameBufferRefs::iterator kFound(std::find(pContextData->m_kBoundFrameBuffers.begin(), pContextData->m_kBoundFrameBuffers.end(), pFrameBuffer));
|
|
if (kFound == pContextData->m_kBoundFrameBuffers.end())
|
|
{
|
|
pContextData->m_kBoundFrameBuffers.push_back(SFrameBufferRef(pFrameBuffer, 1));
|
|
}
|
|
else
|
|
{
|
|
++kFound->m_uNumBindings;
|
|
}
|
|
|
|
// Might need to disable PLS off 1st
|
|
pContext->UpdatePlsState(true);
|
|
|
|
return FrameBufferTexture(pFrameBuffer->m_kObject.m_kName.GetName(), eAttachmentID);
|
|
}
|
|
|
|
void SOutputMergerView::DetachFrameBuffer(SFrameBuffer* pFrameBuffer)
|
|
{
|
|
SContextData* pContextData(m_kContextMap[pFrameBuffer->m_pContext->GetIndex()]);
|
|
if (pContextData == NULL)
|
|
{
|
|
DXGL_ERROR("Frame buffer context has not been registered to this output merger view");
|
|
return;
|
|
}
|
|
|
|
TFrameBufferRefs::iterator kFound(std::find(pContextData->m_kBoundFrameBuffers.begin(), pContextData->m_kBoundFrameBuffers.end(), pFrameBuffer));
|
|
if (kFound != pContextData->m_kBoundFrameBuffers.end())
|
|
{
|
|
if (--kFound->m_uNumBindings == 0)
|
|
{
|
|
pContextData->m_kBoundFrameBuffers.erase(kFound);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DXGL_ERROR("Could not find the frame buffer to be detached from the view");
|
|
}
|
|
}
|
|
|
|
bool SOutputMergerView::FrameBufferTexture(GLuint uFrameBuffer, GLenum eAttachmentID)
|
|
{
|
|
if (m_kUniqueView.IsValid())
|
|
{
|
|
glNamedFramebufferTextureEXT(uFrameBuffer, eAttachmentID, m_kUniqueView.GetName(), 0);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void SOutputMergerView::Bind(const SFrameBuffer&, CContext*)
|
|
{
|
|
}
|
|
|
|
const GLint SOutputMergerTextureView::INVALID_LAYER = -1;
|
|
|
|
SOutputMergerTextureView::SOutputMergerTextureView(STexture* pTexture, const SOutputMergerTextureViewConfiguration& kConfiguration)
|
|
: SOutputMergerView(CResourceName(), kConfiguration.m_eFormat)
|
|
, m_kConfiguration(kConfiguration)
|
|
, m_pTexture(pTexture)
|
|
{
|
|
m_pNextView = pTexture->m_pOutputMergerViewsHead;
|
|
pTexture->m_pOutputMergerViewsHead = this;
|
|
}
|
|
|
|
SOutputMergerTextureView::~SOutputMergerTextureView()
|
|
{
|
|
SOutputMergerTextureView*& pLink = m_pTexture->m_pOutputMergerViewsHead;
|
|
while (pLink != NULL)
|
|
{
|
|
if (pLink == this)
|
|
{
|
|
pLink = m_pNextView;
|
|
}
|
|
else
|
|
{
|
|
pLink = pLink->m_pNextView;
|
|
}
|
|
}
|
|
}
|
|
|
|
bool SOutputMergerTextureView::Init(CContext* pContext)
|
|
{
|
|
m_iMipLevel = (GLint)m_kConfiguration.m_uMipLevel;
|
|
if (m_kConfiguration.m_uMinLayer == 0 && m_kConfiguration.m_uNumLayers == m_pTexture->m_uNumElements)
|
|
{
|
|
m_iLayer = INVALID_LAYER;
|
|
}
|
|
else if (m_kConfiguration.m_uNumLayers == 1)
|
|
{
|
|
m_iLayer = m_kConfiguration.m_uMinLayer;
|
|
}
|
|
else
|
|
{
|
|
DXGL_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
if (m_kConfiguration.m_eFormat != m_pTexture->m_eFormat)
|
|
{
|
|
const SGIFormatInfo* pFormatInfo;
|
|
if (m_kConfiguration.m_eFormat == eGIF_NUM ||
|
|
(pFormatInfo = GetGIFormatInfo(m_kConfiguration.m_eFormat)) == NULL ||
|
|
pFormatInfo->m_pTexture == NULL)
|
|
{
|
|
DXGL_ERROR("Invalid format for output merger view");
|
|
return false;
|
|
}
|
|
|
|
if (pFormatInfo->m_pTexture->m_iInternalFormat == GetGIFormatInfo(m_pTexture->m_eFormat)->m_pTexture->m_iInternalFormat)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
// Frame buffer attachment does not support any kind of in-place conversion - texture view is required unless no conversion is needed at all
|
|
return CreateUniqueView(pFormatInfo, pContext);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool SOutputMergerTextureView::FrameBufferTexture(GLuint uFrameBuffer, GLenum eAttachmentID)
|
|
{
|
|
GLuint uTexture(m_kUniqueView.IsValid() ? m_kUniqueView.GetName() : m_pTexture->m_kName.GetName());
|
|
if (m_iLayer == INVALID_LAYER)
|
|
{
|
|
glNamedFramebufferTextureEXT(uFrameBuffer, eAttachmentID, uTexture, m_iMipLevel);
|
|
}
|
|
else
|
|
{
|
|
glNamedFramebufferTextureLayerEXT(uFrameBuffer, eAttachmentID, uTexture, m_iMipLevel, m_iLayer);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool SOutputMergerTextureView::CreateUniqueView(const SGIFormatInfo* pFormatInfo, CContext* pContext)
|
|
{
|
|
if (pFormatInfo->m_eTypelessFormat != m_pTexture->m_eFormat)
|
|
{
|
|
DXGL_ERROR("Output merger view format is not compatible with texture format");
|
|
return false;
|
|
}
|
|
|
|
m_kUniqueView = CreateTextureView(m_pTexture, pFormatInfo, m_pTexture->m_eTarget, 0, m_pTexture->m_uNumMipLevels, 0, m_pTexture->m_uNumElements, pContext);
|
|
m_pTexture->m_kCreationFence.IssueWait(pContext);
|
|
m_kCreationFence.IssueFence(pContext->GetDevice());
|
|
|
|
return true;
|
|
}
|
|
|
|
SDefaultFrameBufferOutputMergerView::SDefaultFrameBufferOutputMergerView(SDefaultFrameBufferTexture* pTexture, const SOutputMergerTextureViewConfiguration& kConfiguration)
|
|
: SOutputMergerTextureView(pTexture, kConfiguration)
|
|
, m_bUsesTexture(false)
|
|
{
|
|
}
|
|
|
|
SDefaultFrameBufferOutputMergerView::~SDefaultFrameBufferOutputMergerView()
|
|
{
|
|
if (m_bUsesTexture)
|
|
{
|
|
static_cast<SDefaultFrameBufferTexture*>(m_pTexture)->DecTextureRefCount();
|
|
}
|
|
}
|
|
|
|
bool SDefaultFrameBufferOutputMergerView::AttachFrameBuffer(SFrameBuffer* pFrameBuffer, GLenum eAttachmentID, CContext* pContext)
|
|
{
|
|
if (!m_bUsesTexture)
|
|
{
|
|
static_cast<SDefaultFrameBufferTexture*>(m_pTexture)->IncTextureRefCount(pContext);
|
|
m_bUsesTexture = true;
|
|
}
|
|
return SOutputMergerTextureView::AttachFrameBuffer(pFrameBuffer, eAttachmentID, pContext);
|
|
}
|
|
|
|
void SDefaultFrameBufferOutputMergerView::Bind(const SFrameBuffer& kFrameBuffer, CContext* pContext)
|
|
{
|
|
static_cast<SDefaultFrameBufferTexture*>(m_pTexture)->OnWrite(pContext, kFrameBuffer.m_kObject.m_kName.GetName() == 0);
|
|
SOutputMergerTextureView::Bind(kFrameBuffer, pContext);
|
|
}
|
|
|
|
bool SDefaultFrameBufferOutputMergerView::CreateUniqueView(const SGIFormatInfo* pFormatInfo, CContext* pContext)
|
|
{
|
|
if (!m_bUsesTexture)
|
|
{
|
|
static_cast<SDefaultFrameBufferTexture*>(m_pTexture)->IncTextureRefCount(pContext);
|
|
m_bUsesTexture = true;
|
|
}
|
|
return SOutputMergerTextureView::CreateUniqueView(pFormatInfo, pContext);
|
|
}
|
|
|
|
SDefaultFrameBufferShaderTextureView::SDefaultFrameBufferShaderTextureView(const SShaderTextureViewConfiguration& kConfiguration)
|
|
: SShaderTextureView(kConfiguration)
|
|
, m_bUsesTexture(false)
|
|
{
|
|
}
|
|
|
|
SDefaultFrameBufferShaderTextureView::~SDefaultFrameBufferShaderTextureView()
|
|
{
|
|
}
|
|
|
|
bool SDefaultFrameBufferShaderTextureView::BindTextureUnit(SSamplerState* pSamplerState, STextureUnitContext& kContext, CContext* pContext, const STextureUnitCache& kCurrentUnitCache)
|
|
{
|
|
SDefaultFrameBufferTexture* pDefaultFrameBufferTexture(static_cast<SDefaultFrameBufferTexture*>(m_pTexture));
|
|
if (!m_bUsesTexture)
|
|
{
|
|
pDefaultFrameBufferTexture->IncTextureRefCount(pContext);
|
|
m_bUsesTexture = true;
|
|
}
|
|
pDefaultFrameBufferTexture->OnRead(pContext);
|
|
return SShaderTextureView::BindTextureUnit(pSamplerState, kContext, pContext, kCurrentUnitCache);
|
|
}
|
|
|
|
template <typename ViewDesc, typename View>
|
|
struct SResourceViewBaseImpl
|
|
{
|
|
typedef ViewDesc TViewDesc;
|
|
typedef View TView;
|
|
typedef _smart_ptr<TView> TViewPtr;
|
|
};
|
|
|
|
struct SShaderResourceViewImpl
|
|
: SResourceViewBaseImpl<D3D11_SHADER_RESOURCE_VIEW_DESC, SShaderView>
|
|
{
|
|
enum EViewDimension
|
|
{
|
|
DIMENSION_BUFFER = D3D11_SRV_DIMENSION_BUFFER,
|
|
DIMENSION_TEXTURE1D = D3D11_SRV_DIMENSION_TEXTURE1D,
|
|
DIMENSION_TEXTURE1DARRAY = D3D11_SRV_DIMENSION_TEXTURE1DARRAY,
|
|
DIMENSION_TEXTURE2D = D3D11_SRV_DIMENSION_TEXTURE2D,
|
|
DIMENSION_TEXTURE2DARRAY = D3D11_SRV_DIMENSION_TEXTURE2DARRAY,
|
|
DIMENSION_TEXTURE2DMS = D3D11_SRV_DIMENSION_TEXTURE2DMS,
|
|
DIMENSION_TEXTURE2DMSARRAY = D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY,
|
|
DIMENSION_TEXTURE3D = D3D11_SRV_DIMENSION_TEXTURE3D,
|
|
DIMENSION_TEXTURECUBE = D3D11_SRV_DIMENSION_TEXTURECUBE,
|
|
DIMENSION_TEXTURECUBEARRAY = D3D11_SRV_DIMENSION_TEXTURECUBEARRAY,
|
|
DIMENSION_BUFFEREX = D3D11_SRV_DIMENSION_BUFFEREX
|
|
};
|
|
|
|
static SResourceViewBaseImpl::TViewPtr GetView(STexture* pTexture, DXGI_FORMAT eDXGIFormat, GLenum eTarget, uint32 uMinLevel, uint32 uNumLevels, uint32 uMinElement, uint32 uNumElements, CContext* pContext)
|
|
{
|
|
SShaderTextureViewConfiguration kConfiguration(GetGIFormat(eDXGIFormat), eTarget, uMinLevel, uNumLevels, uMinElement, uNumElements);
|
|
|
|
SShaderTextureView* pExistingView(pTexture->m_pShaderViewsHead);
|
|
while (pExistingView != NULL)
|
|
{
|
|
if (pExistingView->m_kConfiguration == kConfiguration)
|
|
{
|
|
return pExistingView;
|
|
}
|
|
pExistingView = pExistingView->m_pNextView;
|
|
}
|
|
|
|
return pTexture->CreateShaderResourceView(kConfiguration, pContext);
|
|
}
|
|
|
|
template <typename DimDesc>
|
|
static TViewPtr GetViewMip(STexture* pTexture, const DimDesc& kDimDesc, DXGI_FORMAT eDXGIFormat, GLenum eTarget, uint32 uMinElement, uint32 uNumElements, CContext* pContext)
|
|
{
|
|
uint32 uNumMipLevels(kDimDesc.MipLevels == -1 ? (pTexture->m_uNumMipLevels - kDimDesc.MostDetailedMip) : kDimDesc.MipLevels);
|
|
return GetView(pTexture, eDXGIFormat, eTarget, kDimDesc.MostDetailedMip, uNumMipLevels, uMinElement, uNumElements, pContext);
|
|
}
|
|
|
|
template <typename DimDesc>
|
|
static TViewPtr GetViewLayers(STexture* pTexture, const DimDesc& kDimDesc, DXGI_FORMAT eDXGIFormat, uint32 uMinLevel, uint32 uNumLevels, GLenum eTarget, CContext* pContext)
|
|
{
|
|
uint32 uNumElements(kDimDesc.ArraySize == -1 ? (pTexture->m_uNumElements - kDimDesc.FirstArraySlice) : kDimDesc.ArraySize);
|
|
return GetView(pTexture, eDXGIFormat, eTarget, uMinLevel, uNumLevels, kDimDesc.FirstArraySlice, uNumElements, pContext);
|
|
}
|
|
|
|
template <typename DimDesc>
|
|
static TViewPtr GetViewMipLayers(STexture* pTexture, const DimDesc& kDimDesc, DXGI_FORMAT eDXGIFormat, GLenum eTarget, CContext* pContext)
|
|
{
|
|
uint32 uNumElements(kDimDesc.ArraySize == -1 ? (pTexture->m_uNumElements - kDimDesc.FirstArraySlice) : kDimDesc.ArraySize);
|
|
return GetViewMip(pTexture, kDimDesc, eDXGIFormat, eTarget, kDimDesc.FirstArraySlice, uNumElements, pContext);
|
|
}
|
|
|
|
template <typename DimDesc>
|
|
static TViewPtr GetView(SBuffer* pBuffer, const DimDesc& kDimDesc, DXGI_FORMAT eDXGIFormat, UINT uFlags, CContext* pContext)
|
|
{
|
|
return pBuffer->CreateShaderResourceView(GetGIFormat(eDXGIFormat), kDimDesc.FirstElement, kDimDesc.NumElements, uFlags, pContext);
|
|
}
|
|
|
|
template <typename DimDesc>
|
|
static TViewPtr GetViewEx(SBuffer* pBuffer, const DimDesc& kDimDesc, DXGI_FORMAT eDXGIFormat, CContext* pContext)
|
|
{
|
|
return GetView(pBuffer, kDimDesc, eDXGIFormat, kDimDesc.Flags, pContext);
|
|
}
|
|
};
|
|
|
|
struct SUnorderedAccessViewImpl
|
|
: SResourceViewBaseImpl<D3D11_UNORDERED_ACCESS_VIEW_DESC, SShaderView>
|
|
{
|
|
enum EViewDimension
|
|
{
|
|
DIMENSION_BUFFER = D3D11_UAV_DIMENSION_BUFFER,
|
|
DIMENSION_TEXTURE1D = D3D11_UAV_DIMENSION_TEXTURE1D,
|
|
DIMENSION_TEXTURE1DARRAY = D3D11_UAV_DIMENSION_TEXTURE1DARRAY,
|
|
DIMENSION_TEXTURE2D = D3D11_UAV_DIMENSION_TEXTURE2D,
|
|
DIMENSION_TEXTURE2DARRAY = D3D11_UAV_DIMENSION_TEXTURE2DARRAY,
|
|
DIMENSION_TEXTURE3D = D3D11_UAV_DIMENSION_TEXTURE3D,
|
|
};
|
|
|
|
static SResourceViewBaseImpl::TViewPtr GetView(STexture* pTexture, DXGI_FORMAT eDXGIFormat, GLenum eTarget, uint32 uMipSlice, uint32 uMinElement, uint32 uNumElements, CContext* pContext)
|
|
{
|
|
EGIFormat eGIFormat(GetGIFormat(eDXGIFormat));
|
|
GLenum eImageFormat(GL_NONE);
|
|
if (!GetImageFormat(eGIFormat, &eImageFormat))
|
|
{
|
|
DXGL_ERROR("Unsupported format for unordered access view");
|
|
return NULL;
|
|
}
|
|
|
|
if (uMinElement == 0 && uNumElements == pTexture->m_uNumElements)
|
|
{
|
|
SShaderImageViewConfiguration kConfiguration(eImageFormat, (GLint)uMipSlice, -1, GL_READ_WRITE);
|
|
return pTexture->CreateUnorderedAccessView(kConfiguration, pContext);
|
|
}
|
|
else if (uNumElements == 1)
|
|
{
|
|
SShaderImageViewConfiguration kConfiguration(eImageFormat, (GLint)uMipSlice, uMinElement, GL_READ_WRITE);
|
|
return pTexture->CreateUnorderedAccessView(kConfiguration, pContext);
|
|
}
|
|
else
|
|
{
|
|
// Need to first create a proxy view containing only the selected layers
|
|
SShaderTextureViewConfiguration kProxyConfiguration(pTexture->m_eFormat, eTarget, uMipSlice, 1, uMinElement, uNumElements);
|
|
SShaderTextureViewPtr spProxyTextureView(pTexture->CreateShaderResourceView(kProxyConfiguration, pContext));
|
|
if (spProxyTextureView == NULL)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
SShaderImageViewConfiguration kConfiguration(eImageFormat, (GLint)uMipSlice, -1, GL_READ_WRITE);
|
|
SShaderImageViewPtr spImageView(new SShaderImageView(kConfiguration));
|
|
if (!spImageView->Init(spProxyTextureView, pContext))
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
return spImageView;
|
|
}
|
|
}
|
|
|
|
template <typename DimDesc>
|
|
static TViewPtr GetViewMip(STexture* pTexture, const DimDesc& kDimDesc, DXGI_FORMAT eDXGIFormat, GLenum eTarget, uint32 uMinElement, uint32 uNumElements, CContext* pContext)
|
|
{
|
|
return GetView(pTexture, eDXGIFormat, eTarget, kDimDesc.MipSlice, uMinElement, uNumElements, pContext);
|
|
}
|
|
|
|
template <typename DimDesc>
|
|
static TViewPtr GetViewLayers(STexture* pTexture, const DimDesc& kDimDesc, DXGI_FORMAT eDXGIFormat, uint32 uMipSlice, GLenum eTarget, CContext* pContext)
|
|
{
|
|
uint32 uNumElements(kDimDesc.ArraySize == -1 ? (pTexture->m_uNumElements - kDimDesc.FirstArraySlice) : kDimDesc.ArraySize);
|
|
return GetView(pTexture, eDXGIFormat, eTarget, uMipSlice, kDimDesc.FirstArraySlice, uNumElements, pContext);
|
|
}
|
|
|
|
template <typename DimDesc>
|
|
static TViewPtr GetViewMipLayers(STexture* pTexture, const DimDesc& kDimDesc, DXGI_FORMAT eDXGIFormat, GLenum eTarget, CContext* pContext)
|
|
{
|
|
uint32 uNumElements(kDimDesc.ArraySize == -1 ? (pTexture->m_uNumElements - kDimDesc.FirstArraySlice) : kDimDesc.ArraySize);
|
|
return GetViewMip(pTexture, kDimDesc, eDXGIFormat, eTarget, kDimDesc.FirstArraySlice, uNumElements, pContext);
|
|
}
|
|
|
|
template <typename DimDesc>
|
|
static TViewPtr GetView(SBuffer* pBuffer, const DimDesc& kDimDesc, DXGI_FORMAT eDXGIFormat, UINT uFlags, CContext* pContext)
|
|
{
|
|
return pBuffer->CreateUnorderedAccessView(GetGIFormat(eDXGIFormat), kDimDesc.FirstElement, kDimDesc.NumElements, uFlags, pContext);
|
|
}
|
|
|
|
template <typename DimDesc>
|
|
static TViewPtr GetViewEx(SBuffer* pBuffer, const DimDesc& kDimDesc, DXGI_FORMAT eDXGIFormat, CContext* pContext)
|
|
{
|
|
return GetView(pBuffer, kDimDesc, eDXGIFormat, kDimDesc, kDimDesc.Flags);
|
|
}
|
|
};
|
|
|
|
template <typename ViewDesc>
|
|
struct SOutputMergerViewImpl
|
|
: SResourceViewBaseImpl<ViewDesc, SOutputMergerView>
|
|
{
|
|
static typename SOutputMergerViewImpl::TViewPtr GetView(STexture* pTexture, DXGI_FORMAT eDXGIFormat, GLenum, uint32 uMipLevel, uint32, uint32 uMinElement, uint32 uNumElements, CContext* pContext)
|
|
{
|
|
return pTexture->GetCompatibleOutputMergerView(SOutputMergerTextureViewConfiguration(GetGIFormat(eDXGIFormat), uMipLevel, uMinElement, uNumElements), pContext);
|
|
}
|
|
|
|
template <typename DimDesc>
|
|
static typename SOutputMergerViewImpl::TViewPtr GetViewMip(STexture* pTexture, const DimDesc& kDimDesc, DXGI_FORMAT eDXGIFormat, GLenum eTarget, uint32 uMinElement, uint32 uNumElements, CContext* pContext)
|
|
{
|
|
return GetView(pTexture, eDXGIFormat, eTarget, kDimDesc.MipSlice, 1, uMinElement, uNumElements, pContext);
|
|
}
|
|
|
|
template <typename DimDesc>
|
|
static typename SOutputMergerViewImpl::TViewPtr GetViewLayers(STexture* pTexture, const DimDesc& kDimDesc, DXGI_FORMAT eDXGIFormat, GLenum eTarget, uint32 uMinLevel, uint32 uNumLevels, CContext* pContext)
|
|
{
|
|
uint32 uNumElements(kDimDesc.ArraySize == -1 ? (pTexture->m_uNumElements - kDimDesc.FirstArraySlice) : kDimDesc.ArraySize);
|
|
return GetView(pTexture, eDXGIFormat, eTarget, uMinLevel, uNumLevels, kDimDesc.FirstArraySlice, uNumElements, pContext);
|
|
}
|
|
|
|
template <typename DimDesc>
|
|
static typename SOutputMergerViewImpl::TViewPtr GetViewMipLayers(STexture* pTexture, const DimDesc& kDimDesc, DXGI_FORMAT eDXGIFormat, GLenum eTarget, CContext* pContext)
|
|
{
|
|
uint32 uNumElements(kDimDesc.ArraySize == -1 ? (pTexture->m_uNumElements - kDimDesc.FirstArraySlice) : kDimDesc.ArraySize);
|
|
return GetViewMip(pTexture, kDimDesc, eDXGIFormat, eTarget, kDimDesc.FirstArraySlice, uNumElements, pContext);
|
|
}
|
|
};
|
|
|
|
struct SRenderTargetViewImpl
|
|
: SOutputMergerViewImpl<D3D11_RENDER_TARGET_VIEW_DESC>
|
|
{
|
|
enum EViewDimension
|
|
{
|
|
DIMENSION_BUFFER = D3D11_RTV_DIMENSION_BUFFER,
|
|
DIMENSION_TEXTURE1D = D3D11_RTV_DIMENSION_TEXTURE1D,
|
|
DIMENSION_TEXTURE1DARRAY = D3D11_RTV_DIMENSION_TEXTURE1DARRAY,
|
|
DIMENSION_TEXTURE2D = D3D11_RTV_DIMENSION_TEXTURE2D,
|
|
DIMENSION_TEXTURE2DARRAY = D3D11_RTV_DIMENSION_TEXTURE2DARRAY,
|
|
DIMENSION_TEXTURE2DMS = D3D11_RTV_DIMENSION_TEXTURE2DMS,
|
|
DIMENSION_TEXTURE2DMSARRAY = D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY,
|
|
DIMENSION_TEXTURE3D = D3D11_RTV_DIMENSION_TEXTURE3D
|
|
};
|
|
};
|
|
|
|
struct SDepthStencilViewImpl
|
|
: SOutputMergerViewImpl<D3D11_DEPTH_STENCIL_VIEW_DESC>
|
|
{
|
|
enum EViewDimension
|
|
{
|
|
DIMENSION_TEXTURE1D = D3D11_DSV_DIMENSION_TEXTURE1D,
|
|
DIMENSION_TEXTURE1DARRAY = D3D11_DSV_DIMENSION_TEXTURE1DARRAY,
|
|
DIMENSION_TEXTURE2D = D3D11_DSV_DIMENSION_TEXTURE2D,
|
|
DIMENSION_TEXTURE2DARRAY = D3D11_DSV_DIMENSION_TEXTURE2DARRAY,
|
|
DIMENSION_TEXTURE2DMS = D3D11_DSV_DIMENSION_TEXTURE2DMS,
|
|
DIMENSION_TEXTURE2DMSARRAY = D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY,
|
|
};
|
|
};
|
|
|
|
template <typename Impl>
|
|
typename Impl::TViewPtr GetTexture1DView(STexture* pTexture, const typename Impl::TViewDesc& kViewDesc, CContext* pContext)
|
|
{
|
|
switch (static_cast<typename Impl::EViewDimension>(kViewDesc.ViewDimension))
|
|
{
|
|
case Impl::DIMENSION_TEXTURE1D:
|
|
return Impl::GetViewMip(pTexture, kViewDesc.Texture1D, kViewDesc.Format, GL_TEXTURE_1D, 0, 1, pContext);
|
|
case Impl::DIMENSION_TEXTURE1DARRAY:
|
|
return Impl::GetViewMipLayers(pTexture, kViewDesc.Texture1DArray, kViewDesc.Format, GL_TEXTURE_1D_ARRAY, pContext);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
template <typename Impl>
|
|
typename Impl::TViewPtr GetTexture2DView(STexture* pTexture, const typename Impl::TViewDesc& kViewDesc, CContext* pContext)
|
|
{
|
|
switch (static_cast<typename Impl::EViewDimension>(kViewDesc.ViewDimension))
|
|
{
|
|
case Impl::DIMENSION_TEXTURE2D:
|
|
return Impl::GetViewMip(pTexture, kViewDesc.Texture2D, kViewDesc.Format, GL_TEXTURE_2D, 0, 1, pContext);
|
|
case Impl::DIMENSION_TEXTURE2DARRAY:
|
|
return Impl::GetViewMipLayers(pTexture, kViewDesc.Texture2DArray, kViewDesc.Format, GL_TEXTURE_2D_ARRAY, pContext);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
template <typename Impl>
|
|
typename Impl::TViewPtr GetTexture2DMSView(STexture* pTexture, const typename Impl::TViewDesc& kViewDesc, CContext* pContext)
|
|
{
|
|
if (pContext->GetDevice()->IsFeatureSupported(eF_MultiSampledTextures))
|
|
{
|
|
switch (static_cast<typename Impl::EViewDimension>(kViewDesc.ViewDimension))
|
|
{
|
|
#if DXGL_SUPPORT_MULTISAMPLED_TEXTURES
|
|
case Impl::DIMENSION_TEXTURE2DMS:
|
|
return Impl::GetView(pTexture, kViewDesc.Format, GL_TEXTURE_2D_MULTISAMPLE, 0, 1, 0, 1, pContext);
|
|
#if !DXGLES
|
|
case Impl::DIMENSION_TEXTURE2DMSARRAY:
|
|
return Impl::GetViewLayers(pTexture, kViewDesc.Texture2DMSArray, kViewDesc.Format, GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 0, 1, pContext);
|
|
#endif //!DXGLES
|
|
#endif //DXGL_SUPPORT_MULTISAMPLED_TEXTURES
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
template <typename Impl>
|
|
typename Impl::TViewPtr GetTextureCubeView(STexture* pTexture, const typename Impl::TViewDesc& kViewDesc, CContext* pContext)
|
|
{
|
|
switch (static_cast<D3D_SRV_DIMENSION>(kViewDesc.ViewDimension))
|
|
{
|
|
case D3D11_SRV_DIMENSION_TEXTURECUBE:
|
|
return Impl::GetViewMip(pTexture, kViewDesc.TextureCube, kViewDesc.Format, GL_TEXTURE_CUBE_MAP, 0, 6, pContext);
|
|
#if DXGL_SUPPORT_CUBEMAP_ARRAYS
|
|
case D3D11_SRV_DIMENSION_TEXTURECUBEARRAY:
|
|
return Impl::GetViewMip(pTexture, kViewDesc.TextureCubeArray, kViewDesc.Format, GL_TEXTURE_CUBE_MAP_ARRAY, kViewDesc.TextureCubeArray.First2DArrayFace, 6 * kViewDesc.TextureCubeArray.NumCubes - kViewDesc.TextureCubeArray.First2DArrayFace, pContext);
|
|
#endif //DXGL_SUPPORT_CUBEMAP_ARRAYS
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
template <typename Impl>
|
|
typename Impl::TViewPtr GetTexture3DView(STexture* pTexture, const typename Impl::TViewDesc& kViewDesc, CContext* pContext)
|
|
{
|
|
if ((uint32)kViewDesc.ViewDimension == (uint32)Impl::DIMENSION_TEXTURE3D)
|
|
{
|
|
return Impl::GetViewMip(pTexture, kViewDesc.Texture3D, kViewDesc.Format, GL_TEXTURE_3D, 0, 1, pContext);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
template <typename Impl>
|
|
typename Impl::TViewPtr GetBufferView(SBuffer* pBuffer, const typename Impl::TViewDesc& kViewDesc, CContext* pContext)
|
|
{
|
|
if ((uint32)kViewDesc.ViewDimension == (uint32)Impl::DIMENSION_BUFFER)
|
|
{
|
|
return Impl::GetView(pBuffer, kViewDesc.Buffer, kViewDesc.Format, 0, pContext);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
template <typename Impl>
|
|
typename Impl::TViewPtr GetBufferViewEx(SBuffer* pBuffer, const typename Impl::TViewDesc& kViewDesc, CContext* pContext)
|
|
{
|
|
if ((uint32)kViewDesc.ViewDimension == (uint32)Impl::DIMENSION_BUFFEREX)
|
|
{
|
|
return Impl::GetViewEx(pBuffer, kViewDesc.BufferEx, kViewDesc.Format, pContext);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
SShaderViewPtr CreateShaderResourceView(SResource* pResource, D3D11_RESOURCE_DIMENSION eDimension, const D3D11_SHADER_RESOURCE_VIEW_DESC& kViewDesc, CContext* pContext)
|
|
{
|
|
DXGL_SCOPED_PROFILE("CreateShaderResourceView")
|
|
|
|
typedef SShaderResourceViewImpl TImpl;
|
|
SShaderViewPtr spView;
|
|
switch (eDimension)
|
|
{
|
|
case D3D11_RESOURCE_DIMENSION_TEXTURE1D:
|
|
spView = GetTexture1DView<TImpl>(static_cast<STexture*>(pResource), kViewDesc, pContext);
|
|
break;
|
|
case D3D11_RESOURCE_DIMENSION_TEXTURE2D:
|
|
spView = GetTexture2DView<TImpl>(static_cast<STexture*>(pResource), kViewDesc, pContext);
|
|
if (spView == NULL)
|
|
{
|
|
spView = GetTexture2DMSView<TImpl>(static_cast<STexture*>(pResource), kViewDesc, pContext);
|
|
}
|
|
if (spView == NULL)
|
|
{
|
|
spView = GetTextureCubeView<TImpl>(static_cast<STexture*>(pResource), kViewDesc, pContext);
|
|
}
|
|
break;
|
|
case D3D11_RESOURCE_DIMENSION_TEXTURE3D:
|
|
spView = GetTexture3DView<TImpl>(static_cast<STexture*>(pResource), kViewDesc, pContext);
|
|
break;
|
|
case D3D11_RESOURCE_DIMENSION_BUFFER:
|
|
spView = GetBufferView<TImpl>(static_cast<SBuffer*>(pResource), kViewDesc, pContext);
|
|
if (spView == NULL)
|
|
{
|
|
spView = GetBufferViewEx<TImpl>(static_cast<SBuffer*>(pResource), kViewDesc, pContext);
|
|
}
|
|
break;
|
|
default:
|
|
DXGL_ERROR("Invalid resource dimension for shader resource");
|
|
return NULL;
|
|
}
|
|
|
|
if (spView == NULL)
|
|
{
|
|
DXGL_ERROR("Invalid shader resource view parameters");
|
|
}
|
|
return spView;
|
|
}
|
|
|
|
SShaderViewPtr CreateUnorderedAccessView(SResource* pResource, D3D11_RESOURCE_DIMENSION eDimension, const D3D11_UNORDERED_ACCESS_VIEW_DESC& kViewDesc, CContext* pContext)
|
|
{
|
|
DXGL_SCOPED_PROFILE("CreateShaderResourceView")
|
|
|
|
typedef SUnorderedAccessViewImpl TImpl;
|
|
SShaderViewPtr spView;
|
|
switch (eDimension)
|
|
{
|
|
case D3D11_RESOURCE_DIMENSION_TEXTURE1D:
|
|
spView = GetTexture1DView<TImpl>(static_cast<STexture*>(pResource), kViewDesc, pContext);
|
|
break;
|
|
case D3D11_RESOURCE_DIMENSION_TEXTURE2D:
|
|
spView = GetTexture2DView<TImpl>(static_cast<STexture*>(pResource), kViewDesc, pContext);
|
|
break;
|
|
case D3D11_RESOURCE_DIMENSION_TEXTURE3D:
|
|
spView = GetTexture3DView<TImpl>(static_cast<STexture*>(pResource), kViewDesc, pContext);
|
|
break;
|
|
case D3D11_RESOURCE_DIMENSION_BUFFER:
|
|
spView = GetBufferView<TImpl>(static_cast<SBuffer*>(pResource), kViewDesc, pContext);
|
|
break;
|
|
default:
|
|
DXGL_ERROR("Invalid resource dimension for shader resource");
|
|
return NULL;
|
|
}
|
|
|
|
if (spView == NULL)
|
|
{
|
|
DXGL_ERROR("Invalid shader resource view parameters");
|
|
}
|
|
return spView;
|
|
}
|
|
|
|
SOutputMergerViewPtr CreateRenderTargetView(SResource* pResource, D3D11_RESOURCE_DIMENSION eDimension, const D3D11_RENDER_TARGET_VIEW_DESC& kViewDesc, CContext* pContext)
|
|
{
|
|
DXGL_SCOPED_PROFILE("CreateRenderTargetView")
|
|
|
|
typedef SRenderTargetViewImpl TImpl;
|
|
SOutputMergerViewPtr spView;
|
|
switch (eDimension)
|
|
{
|
|
case D3D11_RESOURCE_DIMENSION_TEXTURE1D:
|
|
spView = GetTexture1DView<TImpl>(static_cast<STexture*>(pResource), kViewDesc, pContext);
|
|
break;
|
|
case D3D11_RESOURCE_DIMENSION_TEXTURE2D:
|
|
spView = GetTexture2DView<TImpl>(static_cast<STexture*>(pResource), kViewDesc, pContext);
|
|
if (spView == NULL)
|
|
{
|
|
spView = GetTexture2DMSView<TImpl>(static_cast<STexture*>(pResource), kViewDesc, pContext);
|
|
}
|
|
break;
|
|
case D3D11_RESOURCE_DIMENSION_TEXTURE3D:
|
|
spView = GetTexture3DView<TImpl>(static_cast<STexture*>(pResource), kViewDesc, pContext);
|
|
break;
|
|
default:
|
|
DXGL_ERROR("Invalid resource dimension for render target");
|
|
return NULL;
|
|
}
|
|
if (spView == NULL)
|
|
{
|
|
DXGL_ERROR("Invalid resource dimension for render target");
|
|
}
|
|
return spView;
|
|
}
|
|
|
|
SOutputMergerViewPtr CreateDepthStencilView(SResource* pResource, D3D11_RESOURCE_DIMENSION eDimension, const D3D11_DEPTH_STENCIL_VIEW_DESC& kViewDesc, CContext* pContext)
|
|
{
|
|
DXGL_SCOPED_PROFILE("CreateDepthStencilView")
|
|
|
|
typedef SDepthStencilViewImpl TImpl;
|
|
SOutputMergerViewPtr spView;
|
|
switch (eDimension)
|
|
{
|
|
case D3D11_RESOURCE_DIMENSION_TEXTURE1D:
|
|
spView = GetTexture1DView<TImpl>(static_cast<STexture*>(pResource), kViewDesc, pContext);
|
|
break;
|
|
case D3D11_RESOURCE_DIMENSION_TEXTURE2D:
|
|
spView = GetTexture2DView<TImpl>(static_cast<STexture*>(pResource), kViewDesc, pContext);
|
|
if (spView == NULL)
|
|
{
|
|
spView = GetTexture2DMSView<TImpl>(static_cast<STexture*>(pResource), kViewDesc, pContext);
|
|
}
|
|
break;
|
|
default:
|
|
DXGL_ERROR("Invalid resource dimension for depth stencil");
|
|
return NULL;
|
|
}
|
|
if (spView == NULL)
|
|
{
|
|
DXGL_ERROR("Invalid resource dimension for depth stencil");
|
|
}
|
|
return spView;
|
|
}
|
|
}
|