Latte: Clean up OpenGL relics in shared render code

This commit is contained in:
Exzap 2023-12-08 15:19:12 +01:00
parent 646835346c
commit df282ab230
22 changed files with 267 additions and 216 deletions

View File

@ -115,7 +115,7 @@ void LatteTC_RegisterTexture(LatteTexture* tex);
void LatteTC_UnregisterTexture(LatteTexture* tex);
uint32 LatteTexture_CalculateTextureDataHash(LatteTexture* hostTexture);
void LatteTexture_ReloadData(LatteTexture* hostTexture, uint32 textureUnit);
void LatteTexture_ReloadData(LatteTexture* hostTexture);
bool LatteTC_HasTextureChanged(LatteTexture* hostTexture, bool force = false);
void LatteTC_ResetTextureChangeTracker(LatteTexture* hostTexture, bool force = false);

View File

@ -239,8 +239,6 @@ LatteTextureView* LatteMRT_CreateColorBuffer(MPTR colorBufferPhysMem, uint32 wid
textureView = LatteTexture_CreateMapping(colorBufferPhysMem, MPTR_NULL, width, height, viewSlice+1, pitch, tileMode, swizzle, 0, 1, viewSlice, 1, format, Latte::E_DIM::DIM_2D_ARRAY, Latte::E_DIM::DIM_2D, false);
else
textureView = LatteTexture_CreateMapping(colorBufferPhysMem, MPTR_NULL, width, height, 1, pitch, tileMode, swizzle, 0, 1, viewSlice, 1, format, Latte::E_DIM::DIM_2D, Latte::E_DIM::DIM_2D, false);
// unbind texture
g_renderer->texture_bindAndActivate(nullptr, 0);
return textureView;
}
@ -253,8 +251,6 @@ LatteTextureView* LatteMRT_CreateDepthBuffer(MPTR depthBufferPhysMem, uint32 wid
textureView = LatteTexture_CreateMapping(depthBufferPhysMem, MPTR_NULL, width, height, viewSlice+1, pitch, tileMode, swizzle, 0, 1, viewSlice, 1, format, Latte::E_DIM::DIM_2D_ARRAY, Latte::E_DIM::DIM_2D, true);
LatteMRT::SetDepthAndStencilAttachment(textureView, textureView->baseTexture->hasStencil);
// unbind texture
g_renderer->texture_bindAndActivate(nullptr, 0);
return textureView;
}

View File

@ -985,7 +985,7 @@ void LatteTexture_RecreateTextureWithDifferentMipSliceCount(LatteTexture* textur
newDim = Latte::E_DIM::DIM_2D_ARRAY;
else if (newDim == Latte::E_DIM::DIM_1D && newDepth > 1)
newDim = Latte::E_DIM::DIM_1D_ARRAY;
LatteTextureView* view = LatteTexture_CreateTexture(0, newDim, texture->physAddress, physMipAddr, texture->format, texture->width, texture->height, newDepth, texture->pitch, newMipCount, texture->swizzle, texture->tileMode, texture->isDepth);
LatteTextureView* view = LatteTexture_CreateTexture(newDim, texture->physAddress, physMipAddr, texture->format, texture->width, texture->height, newDepth, texture->pitch, newMipCount, texture->swizzle, texture->tileMode, texture->isDepth);
cemu_assert(!(view->baseTexture->mipLevels <= 1 && physMipAddr == MPTR_NULL && newMipCount > 1));
// copy data from old texture if its dynamically updated
if (texture->isUpdatedOnGPU)
@ -1112,7 +1112,7 @@ LatteTextureView* LatteTexture_CreateMapping(MPTR physAddr, MPTR physMipAddr, si
// create new texture
if (allowCreateNewDataTexture == false)
return nullptr;
LatteTextureView* view = LatteTexture_CreateTexture(0, dimBase, physAddr, physMipAddr, format, width, height, depth, pitch, firstMip + numMip, swizzle, tileMode, isDepth);
LatteTextureView* view = LatteTexture_CreateTexture(dimBase, physAddr, physMipAddr, format, width, height, depth, pitch, firstMip + numMip, swizzle, tileMode, isDepth);
LatteTexture* newTexture = view->baseTexture;
LatteTexture_GatherTextureRelations(view->baseTexture);
LatteTexture_UpdateTextureFromDynamicChanges(view->baseTexture);
@ -1191,12 +1191,8 @@ LatteTextureView* LatteTC_GetTextureSliceViewOrTryCreate(MPTR srcImagePtr, MPTR
void LatteTexture_UpdateDataToLatest(LatteTexture* texture)
{
if (LatteTC_HasTextureChanged(texture))
{
g_renderer->texture_rememberBoundTexture(0);
g_renderer->texture_bindAndActivateRawTex(texture, 0);
LatteTexture_ReloadData(texture, 0);
g_renderer->texture_restoreBoundTexture(0);
}
LatteTexture_ReloadData(texture);
if (texture->reloadFromDynamicTextures)
{
LatteTexture_UpdateCacheFromDynamicTextures(texture);
@ -1245,7 +1241,7 @@ std::vector<LatteTexture*>& LatteTexture::GetAllTextures()
return sAllTextures;
}
LatteTexture::LatteTexture(uint32 textureUnit, Latte::E_DIM dim, MPTR physAddress, MPTR physMipAddress, Latte::E_GX2SURFFMT format, uint32 width, uint32 height, uint32 depth, uint32 pitch, uint32 mipLevels, uint32 swizzle,
LatteTexture::LatteTexture(Latte::E_DIM dim, MPTR physAddress, MPTR physMipAddress, Latte::E_GX2SURFFMT format, uint32 width, uint32 height, uint32 depth, uint32 pitch, uint32 mipLevels, uint32 swizzle,
Latte::E_HWTILEMODE tileMode, bool isDepth)
{
_AddTextureToGlobalList(this);

View File

@ -24,11 +24,9 @@ struct LatteSamplerState
class LatteTexture
{
public:
LatteTexture(uint32 textureUnit, Latte::E_DIM dim, MPTR physAddress, MPTR physMipAddress, Latte::E_GX2SURFFMT format, uint32 width, uint32 height, uint32 depth, uint32 pitch, uint32 mipLevels, uint32 swizzle, Latte::E_HWTILEMODE tileMode, bool isDepth);
LatteTexture(Latte::E_DIM dim, MPTR physAddress, MPTR physMipAddress, Latte::E_GX2SURFFMT format, uint32 width, uint32 height, uint32 depth, uint32 pitch, uint32 mipLevels, uint32 swizzle, Latte::E_HWTILEMODE tileMode, bool isDepth);
virtual ~LatteTexture();
virtual void InitTextureState() {};
LatteTextureView* GetOrCreateView(Latte::E_DIM dim, Latte::E_GX2SURFFMT format, sint32 firstMip, sint32 mipCount, sint32 firstSlice, sint32 sliceCount)
{
for (auto& itr : views)
@ -307,7 +305,7 @@ std::vector<LatteTextureInformation> LatteTexture_QueryCacheInfo();
float* LatteTexture_getEffectiveTextureScale(LatteConst::ShaderType shaderType, sint32 texUnit);
LatteTextureView* LatteTexture_CreateTexture(uint32 textureUnit, Latte::E_DIM dim, MPTR physAddress, MPTR physMipAddress, Latte::E_GX2SURFFMT format, uint32 width, uint32 height, uint32 depth, uint32 pitch, uint32 mipLevels, uint32 swizzle, Latte::E_HWTILEMODE tileMode, bool isDepth);
LatteTextureView* LatteTexture_CreateTexture(Latte::E_DIM dim, MPTR physAddress, MPTR physMipAddress, Latte::E_GX2SURFFMT format, uint32 width, uint32 height, uint32 depth, uint32 pitch, uint32 mipLevels, uint32 swizzle, Latte::E_HWTILEMODE tileMode, bool isDepth);
void LatteTexture_Delete(LatteTexture* texture);
void LatteTextureLoader_writeReadbackTextureToMemory(LatteTextureDefinition* textureData, uint32 sliceIndex, uint32 mipIndex, uint8* linearPixelData);

View File

@ -32,9 +32,9 @@ void LatteTexture_setEffectiveTextureScale(LatteConst::ShaderType shaderType, si
t[1] = v;
}
void LatteTextureLoader_UpdateTextureSliceData(LatteTexture* tex, sint32 textureUnit, uint32 sliceIndex, uint32 mipIndex, MPTR physImagePtr, MPTR physMipPtr, Latte::E_DIM dim, uint32 width, uint32 height, uint32 depth, uint32 mipLevels, uint32 pitch, Latte::E_HWTILEMODE tileMode, uint32 swizzle, bool dumpTex);
void LatteTextureLoader_UpdateTextureSliceData(LatteTexture* tex, uint32 sliceIndex, uint32 mipIndex, MPTR physImagePtr, MPTR physMipPtr, Latte::E_DIM dim, uint32 width, uint32 height, uint32 depth, uint32 mipLevels, uint32 pitch, Latte::E_HWTILEMODE tileMode, uint32 swizzle, bool dumpTex);
void LatteTexture_ReloadData(LatteTexture* tex, uint32 textureUnit)
void LatteTexture_ReloadData(LatteTexture* tex)
{
tex->reloadCount++;
for(sint32 mip=0; mip<tex->mipLevels; mip++)
@ -44,35 +44,35 @@ void LatteTexture_ReloadData(LatteTexture* tex, uint32 textureUnit)
{
sint32 numSlices = std::max(tex->depth, 1);
for(sint32 s=0; s<numSlices; s++)
LatteTextureLoader_UpdateTextureSliceData(tex, textureUnit, s, mip, tex->physAddress, tex->physMipAddress, tex->dim, tex->width, tex->height, tex->depth, tex->mipLevels, tex->pitch, tex->tileMode, tex->swizzle, true);
LatteTextureLoader_UpdateTextureSliceData(tex, s, mip, tex->physAddress, tex->physMipAddress, tex->dim, tex->width, tex->height, tex->depth, tex->mipLevels, tex->pitch, tex->tileMode, tex->swizzle, true);
}
else if( tex->dim == Latte::E_DIM::DIM_CUBEMAP )
{
cemu_assert_debug((tex->depth % 6) == 0);
sint32 numFullCubeMaps = tex->depth/6; // number of cubemaps (if numFullCubeMaps is >1 then this texture is a cubemap array)
for(sint32 s=0; s<numFullCubeMaps*6; s++)
LatteTextureLoader_UpdateTextureSliceData(tex, textureUnit, s, mip, tex->physAddress, tex->physMipAddress, tex->dim, tex->width, tex->height, tex->depth, tex->mipLevels, tex->pitch, tex->tileMode, tex->swizzle, true);
LatteTextureLoader_UpdateTextureSliceData(tex, s, mip, tex->physAddress, tex->physMipAddress, tex->dim, tex->width, tex->height, tex->depth, tex->mipLevels, tex->pitch, tex->tileMode, tex->swizzle, true);
}
else if( tex->dim == Latte::E_DIM::DIM_3D )
{
sint32 mipDepth = std::max(tex->depth>>mip, 1);
for(sint32 s=0; s<mipDepth; s++)
{
LatteTextureLoader_UpdateTextureSliceData(tex, textureUnit, s, mip, tex->physAddress, tex->physMipAddress, tex->dim, tex->width, tex->height, tex->depth, tex->mipLevels, tex->pitch, tex->tileMode, tex->swizzle, true);
LatteTextureLoader_UpdateTextureSliceData(tex, s, mip, tex->physAddress, tex->physMipAddress, tex->dim, tex->width, tex->height, tex->depth, tex->mipLevels, tex->pitch, tex->tileMode, tex->swizzle, true);
}
}
else
{
// load slice 0
LatteTextureLoader_UpdateTextureSliceData(tex, textureUnit, 0, mip, tex->physAddress, tex->physMipAddress, tex->dim, tex->width, tex->height, tex->depth, tex->mipLevels, tex->pitch, tex->tileMode, tex->swizzle, true);
LatteTextureLoader_UpdateTextureSliceData(tex, 0, mip, tex->physAddress, tex->physMipAddress, tex->dim, tex->width, tex->height, tex->depth, tex->mipLevels, tex->pitch, tex->tileMode, tex->swizzle, true);
}
}
tex->lastUpdateEventCounter = LatteTexture_getNextUpdateEventCounter();
}
LatteTextureView* LatteTexture_CreateTexture(uint32 textureUnit, Latte::E_DIM dim, MPTR physAddress, MPTR physMipAddress, Latte::E_GX2SURFFMT format, uint32 width, uint32 height, uint32 depth, uint32 pitch, uint32 mipLevels, uint32 swizzle, Latte::E_HWTILEMODE tileMode, bool isDepth)
LatteTextureView* LatteTexture_CreateTexture(Latte::E_DIM dim, MPTR physAddress, MPTR physMipAddress, Latte::E_GX2SURFFMT format, uint32 width, uint32 height, uint32 depth, uint32 pitch, uint32 mipLevels, uint32 swizzle, Latte::E_HWTILEMODE tileMode, bool isDepth)
{
const auto tex = g_renderer->texture_createTextureEx(textureUnit, dim, physAddress, physMipAddress, format, width, height, depth, pitch, mipLevels, swizzle, tileMode, isDepth);
const auto tex = g_renderer->texture_createTextureEx(dim, physAddress, physMipAddress, format, width, height, depth, pitch, mipLevels, swizzle, tileMode, isDepth);
// init slice/mip info array
LatteTexture_InitSliceAndMipInfo(tex);
LatteTexture_RegisterTextureMemoryOccupancy(tex);
@ -110,7 +110,7 @@ LatteTextureView* LatteTexture_CreateTexture(uint32 textureUnit, Latte::E_DIM di
}
}
}
LatteTexture_ReloadData(tex, textureUnit);
LatteTexture_ReloadData(tex);
LatteTC_MarkTextureStillInUse(tex);
LatteTC_RegisterTexture(tex);
// create initial view that maps to the whole texture
@ -247,7 +247,7 @@ void LatteTexture_updateTexturesForStage(LatteDecompilerShader* shaderContext, u
textureView->lastTextureBindIndex = LatteGPUState.textureBindCounter;
rendererGL->renderstate_updateTextureSettingsGL(shaderContext, textureView, textureIndex + glBackendBaseTexUnit, word4, textureIndex, isDepthSampler);
}
g_renderer->texture_bindOnly(textureView, textureIndex + glBackendBaseTexUnit);
g_renderer->texture_setLatteTexture(textureView, textureIndex + glBackendBaseTexUnit);
// update if data changed
bool swizzleChanged = false;
if (textureView->baseTexture->swizzle != swizzle)
@ -285,9 +285,8 @@ void LatteTexture_updateTexturesForStage(LatteDecompilerShader* shaderContext, u
textureView->baseTexture->physMipAddress = physMipAddr;
}
}
g_renderer->texture_bindAndActivateRawTex(textureView->baseTexture, textureIndex + glBackendBaseTexUnit);
debug_printf("Reload reason: Data-change when bound as texture (new hash 0x%08x)\n", textureView->baseTexture->texDataHash2);
LatteTexture_ReloadData(textureView->baseTexture, textureIndex + glBackendBaseTexUnit);
LatteTexture_ReloadData(textureView->baseTexture);
}
LatteTexture* baseTexture = textureView->baseTexture;
if (baseTexture->reloadFromDynamicTextures)

View File

@ -599,7 +599,7 @@ void LatteTextureLoader_loadTextureDataIntoSlice(LatteTexture* hostTexture, sint
}
}
void LatteTextureLoader_UpdateTextureSliceData(LatteTexture* tex, sint32 textureUnit, uint32 sliceIndex, uint32 mipIndex, MPTR physImagePtr, MPTR physMipPtr, Latte::E_DIM dim, uint32 width, uint32 height, uint32 depth, uint32 mipLevels, uint32 pitch, Latte::E_HWTILEMODE tileMode, uint32 swizzle, bool dumpTex)
void LatteTextureLoader_UpdateTextureSliceData(LatteTexture* tex, uint32 sliceIndex, uint32 mipIndex, MPTR physImagePtr, MPTR physMipPtr, Latte::E_DIM dim, uint32 width, uint32 height, uint32 depth, uint32 mipLevels, uint32 pitch, Latte::E_HWTILEMODE tileMode, uint32 swizzle, bool dumpTex)
{
LatteTextureLoaderCtx textureLoader = { 0 };

View File

@ -44,7 +44,7 @@ LatteTextureView* LatteHandleOSScreen_getOrCreateScreenTex(MPTR physAddress, uin
LatteTextureView* texView = LatteTextureViewLookupCache::lookup(physAddress, width, height, 1, pitch, 0, 1, 0, 1, Latte::E_GX2SURFFMT::R8_G8_B8_A8_UNORM, Latte::E_DIM::DIM_2D);
if (texView)
return texView;
return LatteTexture_CreateTexture(0, Latte::E_DIM::DIM_2D, physAddress, 0, Latte::E_GX2SURFFMT::R8_G8_B8_A8_UNORM, width, height, 1, pitch, 1, 0, Latte::E_HWTILEMODE::TM_LINEAR_ALIGNED, false);
return LatteTexture_CreateTexture(Latte::E_DIM::DIM_2D, physAddress, 0, Latte::E_GX2SURFFMT::R8_G8_B8_A8_UNORM, width, height, 1, pitch, 1, 0, Latte::E_HWTILEMODE::TM_LINEAR_ALIGNED, false);
}
void LatteHandleOSScreen_prepareTextures()
@ -71,8 +71,7 @@ bool LatteHandleOSScreen_TV()
const uint32 bufferIndexTV = (bufferDisplayTV);
const uint32 bufferIndexDRC = bufferDisplayDRC;
g_renderer->texture_bindAndActivate(osScreenTVTex[bufferIndexTV], 0);
LatteTexture_ReloadData(osScreenTVTex[bufferIndexTV]->baseTexture, 0);
LatteTexture_ReloadData(osScreenTVTex[bufferIndexTV]->baseTexture);
// TV screen
LatteRenderTarget_copyToBackbuffer(osScreenTVTex[bufferIndexTV]->baseTexture->baseView, false);
@ -94,8 +93,7 @@ bool LatteHandleOSScreen_DRC()
const uint32 bufferIndexDRC = bufferDisplayDRC;
g_renderer->texture_bindAndActivate(osScreenDRCTex[bufferIndexDRC], 0);
LatteTexture_ReloadData(osScreenDRCTex[bufferIndexDRC]->baseTexture, 0);
LatteTexture_ReloadData(osScreenDRCTex[bufferIndexDRC]->baseTexture);
// GamePad screen
LatteRenderTarget_copyToBackbuffer(osScreenDRCTex[bufferIndexDRC]->baseTexture->baseView, true);

View File

@ -19,20 +19,17 @@ static GLuint _genTextureHandleGL()
return texIdPool[texIdPoolIndex - 1];
}
LatteTextureGL::LatteTextureGL(uint32 textureUnit, Latte::E_DIM dim, MPTR physAddress, MPTR physMipAddress, Latte::E_GX2SURFFMT format, uint32 width, uint32 height, uint32 depth, uint32 pitch, uint32 mipLevels, uint32 swizzle,
LatteTextureGL::LatteTextureGL(Latte::E_DIM dim, MPTR physAddress, MPTR physMipAddress, Latte::E_GX2SURFFMT format, uint32 width, uint32 height, uint32 depth, uint32 pitch, uint32 mipLevels, uint32 swizzle,
Latte::E_HWTILEMODE tileMode, bool isDepth)
: LatteTexture(textureUnit, dim, physAddress, physMipAddress, format, width, height, depth, pitch, mipLevels, swizzle, tileMode, isDepth)
: LatteTexture(dim, physAddress, physMipAddress, format, width, height, depth, pitch, mipLevels, swizzle, tileMode, isDepth)
{
GenerateEmptyTextureFromGX2Dim(dim, this->glId_texture, this->glTexTarget);
GenerateEmptyTextureFromGX2Dim(dim, this->glId_texture, this->glTexTarget, true);
// set format info
FormatInfoGL glFormatInfo;
GetOpenGLFormatInfo(isDepth, format, dim, &glFormatInfo);
this->glInternalFormat = glFormatInfo.glInternalFormat;
this->isAlternativeFormat = glFormatInfo.isUsingAlternativeFormat;
this->hasStencil = glFormatInfo.hasStencil; // todo - should get this from the GX2 format?
// bind texture
g_renderer->texture_bindAndActivateRawTex(this, textureUnit);
LatteTextureGL::InitTextureState();
// set debug name
bool useGLDebugNames = false;
#ifdef CEMU_DEBUG_ASSERT
@ -54,9 +51,8 @@ LatteTextureGL::~LatteTextureGL()
catchOpenGLError();
}
void LatteTextureGL::GenerateEmptyTextureFromGX2Dim(Latte::E_DIM dim, GLuint& texId, GLint& texTarget)
void LatteTextureGL::GenerateEmptyTextureFromGX2Dim(Latte::E_DIM dim, GLuint& texId, GLint& texTarget, bool createForTargetType)
{
texId = _genTextureHandleGL();
if (dim == Latte::E_DIM::DIM_2D)
texTarget = GL_TEXTURE_2D;
else if (dim == Latte::E_DIM::DIM_1D)
@ -73,6 +69,10 @@ void LatteTextureGL::GenerateEmptyTextureFromGX2Dim(Latte::E_DIM dim, GLuint& te
{
cemu_assert_unimplemented();
}
if(createForTargetType)
texId = glCreateTextureWrapper(texTarget); // initializes the texture to texTarget (equivalent to calling glGenTextures + glBindTexture)
else
glGenTextures(1, &texId);
}
LatteTextureView* LatteTextureGL::CreateView(Latte::E_DIM dim, Latte::E_GX2SURFFMT format, sint32 firstMip, sint32 mipCount, sint32 firstSlice, sint32 sliceCount)
@ -80,18 +80,6 @@ LatteTextureView* LatteTextureGL::CreateView(Latte::E_DIM dim, Latte::E_GX2SURFF
return new LatteTextureViewGL(this, dim, format, firstMip, mipCount, firstSlice, sliceCount);
}
void LatteTextureGL::InitTextureState()
{
// init texture with some default parameters (todo - this shouldn't be necessary if we properly set parameters when a texture is used)
catchOpenGLError();
glTexParameteri(glTexTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(glTexTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(glTexTarget, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(glTexTarget, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(glTexTarget, GL_TEXTURE_COMPARE_MODE, GL_NONE);
catchOpenGLError();
}
void LatteTextureGL::GetOpenGLFormatInfo(bool isDepth, Latte::E_GX2SURFFMT format, Latte::E_DIM dim, FormatInfoGL* formatInfoOut)
{
formatInfoOut->isUsingAlternativeFormat = false;

View File

@ -6,14 +6,12 @@
class LatteTextureGL : public LatteTexture
{
public:
LatteTextureGL(uint32 textureUnit, Latte::E_DIM dim, MPTR physAddress, MPTR physMipAddress, Latte::E_GX2SURFFMT format, uint32 width, uint32 height, uint32 depth, uint32 pitch, uint32 mipLevels,
LatteTextureGL(Latte::E_DIM dim, MPTR physAddress, MPTR physMipAddress, Latte::E_GX2SURFFMT format, uint32 width, uint32 height, uint32 depth, uint32 pitch, uint32 mipLevels,
uint32 swizzle, Latte::E_HWTILEMODE tileMode, bool isDepth);
~LatteTextureGL();
static void GenerateEmptyTextureFromGX2Dim(Latte::E_DIM dim, GLuint& texId, GLint& texTarget);
void InitTextureState() override;
static void GenerateEmptyTextureFromGX2Dim(Latte::E_DIM dim, GLuint& texId, GLint& texTarget, bool createForTargetType);
protected:
LatteTextureView* CreateView(Latte::E_DIM dim, Latte::E_GX2SURFFMT format, sint32 firstMip, sint32 mipCount, sint32 firstSlice, sint32 sliceCount) override;

View File

@ -11,7 +11,7 @@ LatteTextureViewGL::LatteTextureViewGL(LatteTextureGL* texture, Latte::E_DIM dim
firstSlice != 0 || firstMip != 0 || mipCount != texture->mipLevels || sliceCount != texture->depth ||
forceCreateNewTexId)
{
LatteTextureGL::GenerateEmptyTextureFromGX2Dim(dim, glTexId, glTexTarget);
LatteTextureGL::GenerateEmptyTextureFromGX2Dim(dim, glTexId, glTexTarget, false);
this->glInternalFormat = 0;
InitAliasView();
}

View File

@ -77,8 +77,6 @@ static const GLenum glAlphaTestFunc[] =
GL_ALWAYS
};
OpenGLRenderer::OpenGLRenderer()
{
glRendererState.useTextureUploadBuffer = false;
@ -571,7 +569,7 @@ void OpenGLRenderer::DrawBackbufferQuad(LatteTextureView* texView, RendererOutpu
glViewportIndexedf(0, imageX, imageY, imageWidth, imageHeight);
LatteTextureViewGL* texViewGL = (LatteTextureViewGL*)texView;
g_renderer->texture_bindAndActivate(texView, 0);
texture_bindAndActivate(texView, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, useLinearTexFilter ? GL_LINEAR : GL_NEAREST);
texViewGL->samplerState.filterMag = 0xFFFFFFFF;
@ -586,7 +584,7 @@ void OpenGLRenderer::DrawBackbufferQuad(LatteTextureView* texView, RendererOutpu
glEnable(GL_FRAMEBUFFER_SRGB);
// unbind texture
g_renderer->texture_bindAndActivate(nullptr, 0);
texture_bindAndActivate(nullptr, 0);
catchOpenGLError();
@ -990,8 +988,9 @@ void OpenGLRenderer::texture_destroy(LatteTexture* hostTexture)
delete hostTexture;
}
void OpenGLRenderer::texture_reserveTextureOnGPU(LatteTexture* hostTexture)
void OpenGLRenderer::texture_reserveTextureOnGPU(LatteTexture* hostTextureGeneric)
{
auto hostTexture = (LatteTextureGL*)hostTextureGeneric;
cemu_assert_debug(hostTexture->isDataDefined == false);
sint32 effectiveBaseWidth = hostTexture->width;
sint32 effectiveBaseHeight = hostTexture->height;
@ -1012,25 +1011,25 @@ void OpenGLRenderer::texture_reserveTextureOnGPU(LatteTexture* hostTexture)
if (hostTexture->dim == Latte::E_DIM::DIM_2D || hostTexture->dim == Latte::E_DIM::DIM_2D_MSAA)
{
cemu_assert_debug(effectiveBaseDepth == 1);
glTexStorage2D(GL_TEXTURE_2D, mipLevels, glFormatInfo.glInternalFormat, effectiveBaseWidth, effectiveBaseHeight);
glTextureStorage2DWrapper(GL_TEXTURE_2D, hostTexture->glId_texture, mipLevels, glFormatInfo.glInternalFormat, effectiveBaseWidth, effectiveBaseHeight);
}
else if (hostTexture->dim == Latte::E_DIM::DIM_1D)
{
cemu_assert_debug(effectiveBaseHeight == 1);
cemu_assert_debug(effectiveBaseDepth == 1);
glTexStorage1D(GL_TEXTURE_1D, mipLevels, glFormatInfo.glInternalFormat, effectiveBaseWidth);
glTextureStorage1DWrapper(GL_TEXTURE_1D, hostTexture->glId_texture, mipLevels, glFormatInfo.glInternalFormat, effectiveBaseWidth);
}
else if (hostTexture->dim == Latte::E_DIM::DIM_2D_ARRAY || hostTexture->dim == Latte::E_DIM::DIM_2D_ARRAY_MSAA)
{
glTexStorage3D(GL_TEXTURE_2D_ARRAY, mipLevels, glFormatInfo.glInternalFormat, effectiveBaseWidth, effectiveBaseHeight, std::max(1, effectiveBaseDepth));
glTextureStorage3DWrapper(GL_TEXTURE_2D_ARRAY, hostTexture->glId_texture, mipLevels, glFormatInfo.glInternalFormat, effectiveBaseWidth, effectiveBaseHeight, std::max(1, effectiveBaseDepth));
}
else if (hostTexture->dim == Latte::E_DIM::DIM_3D)
{
glTexStorage3D(GL_TEXTURE_3D, mipLevels, glFormatInfo.glInternalFormat, effectiveBaseWidth, effectiveBaseHeight, std::max(1, effectiveBaseDepth));
glTextureStorage3DWrapper(GL_TEXTURE_3D, hostTexture->glId_texture, mipLevels, glFormatInfo.glInternalFormat, effectiveBaseWidth, effectiveBaseHeight, std::max(1, effectiveBaseDepth));
}
else if (hostTexture->dim == Latte::E_DIM::DIM_CUBEMAP)
{
glTexStorage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mipLevels, glFormatInfo.glInternalFormat, effectiveBaseWidth, effectiveBaseHeight, effectiveBaseDepth);
glTextureStorage3DWrapper(GL_TEXTURE_CUBE_MAP_ARRAY, hostTexture->glId_texture, mipLevels, glFormatInfo.glInternalFormat, effectiveBaseWidth, effectiveBaseHeight, effectiveBaseDepth);
}
else
{
@ -1042,7 +1041,6 @@ void OpenGLRenderer::texture_reserveTextureOnGPU(LatteTexture* hostTexture)
void OpenGLRenderer_texture_loadSlice_normal(LatteTexture* hostTextureGeneric, sint32 width, sint32 height, sint32 depth, void* pixelData, sint32 sliceIndex, sint32 mipIndex, uint32 imageSize)
{
auto hostTexture = (LatteTextureGL*)hostTextureGeneric;
sint32 effectiveWidth = width;
sint32 effectiveHeight = height;
sint32 effectiveDepth = depth;
@ -1053,58 +1051,37 @@ void OpenGLRenderer_texture_loadSlice_normal(LatteTexture* hostTextureGeneric, s
LatteTextureGL::GetOpenGLFormatInfo(hostTexture->isDepth, hostTexture->overwriteInfo.hasFormatOverwrite ? (Latte::E_GX2SURFFMT)hostTexture->overwriteInfo.format : hostTexture->format, hostTexture->dim, &glFormatInfo);
// upload slice
catchOpenGLError();
if (mipIndex >= hostTexture->maxPossibleMipLevels)
{
cemuLog_logDebug(LogType::Force, "2D texture mip level allocated out of range");
return;
}
if (hostTexture->dim == Latte::E_DIM::DIM_2D || hostTexture->dim == Latte::E_DIM::DIM_2D_MSAA)
{
if (glFormatInfo.glIsCompressed)
{
if (glCompressedTextureSubImage2D)
glCompressedTextureSubImage2D(hostTexture->glId_texture, mipIndex, 0, 0, effectiveWidth, effectiveHeight, glFormatInfo.glInternalFormat, imageSize, pixelData);
else
glCompressedTexSubImage2D(GL_TEXTURE_2D, mipIndex, 0, 0, effectiveWidth, effectiveHeight, glFormatInfo.glInternalFormat, imageSize, pixelData);
}
glCompressedTextureSubImage2DWrapper(hostTexture->glTexTarget, hostTexture->glId_texture, mipIndex, 0, 0, effectiveWidth, effectiveHeight, glFormatInfo.glInternalFormat, imageSize, pixelData);
else
{
if (mipIndex < hostTexture->maxPossibleMipLevels)
glTexSubImage2D(GL_TEXTURE_2D, mipIndex, 0, 0, effectiveWidth, effectiveHeight, glFormatInfo.glSuppliedFormat, glFormatInfo.glSuppliedFormatType, pixelData);
else
cemuLog_logDebug(LogType::Force, "2D texture mip level allocated out of range");
}
glTextureSubImage2DWrapper(hostTexture->glTexTarget, hostTexture->glId_texture, mipIndex, 0, 0, effectiveWidth, effectiveHeight, glFormatInfo.glSuppliedFormat, glFormatInfo.glSuppliedFormatType, pixelData);
}
else if (hostTexture->dim == Latte::E_DIM::DIM_1D)
{
if (glFormatInfo.glIsCompressed == true)
cemu_assert_unimplemented();
glTexSubImage1D(GL_TEXTURE_1D, mipIndex, 0, width, glFormatInfo.glSuppliedFormat, glFormatInfo.glSuppliedFormatType, pixelData);
if (glFormatInfo.glIsCompressed)
glCompressedTextureSubImage1DWrapper(hostTexture->glTexTarget, hostTexture->glId_texture, mipIndex, 0, width, glFormatInfo.glInternalFormat, imageSize, pixelData);
else
glTextureSubImage1DWrapper(hostTexture->glTexTarget, hostTexture->glId_texture, mipIndex, 0, width, glFormatInfo.glSuppliedFormat, glFormatInfo.glSuppliedFormatType, pixelData);
}
else if (hostTexture->dim == Latte::E_DIM::DIM_2D_ARRAY || hostTexture->dim == Latte::E_DIM::DIM_2D_ARRAY_MSAA)
else if (hostTexture->dim == Latte::E_DIM::DIM_2D_ARRAY || hostTexture->dim == Latte::E_DIM::DIM_2D_ARRAY_MSAA ||
hostTexture->dim == Latte::E_DIM::DIM_3D ||
hostTexture->dim == Latte::E_DIM::DIM_CUBEMAP)
{
if (glFormatInfo.glIsCompressed)
glCompressedTexSubImage3D(GL_TEXTURE_2D_ARRAY, mipIndex, 0, 0, sliceIndex, effectiveWidth, effectiveHeight, 1, glFormatInfo.glInternalFormat, imageSize, pixelData);
glCompressedTextureSubImage3DWrapper(hostTexture->glTexTarget, hostTexture->glId_texture, mipIndex, 0, 0, sliceIndex, effectiveWidth, effectiveHeight, 1, glFormatInfo.glInternalFormat, imageSize, pixelData);
else
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, mipIndex, 0, 0, sliceIndex, effectiveWidth, effectiveHeight, 1, glFormatInfo.glSuppliedFormat, glFormatInfo.glSuppliedFormatType, pixelData);
}
else if (hostTexture->dim == Latte::E_DIM::DIM_3D)
{
if (glFormatInfo.glIsCompressed)
glCompressedTexSubImage3D(GL_TEXTURE_3D, mipIndex, 0, 0, sliceIndex, effectiveWidth, effectiveHeight, 1, glFormatInfo.glInternalFormat, imageSize, pixelData);
else
glTexSubImage3D(GL_TEXTURE_3D, mipIndex, 0, 0, sliceIndex, effectiveWidth, effectiveHeight, 1, glFormatInfo.glSuppliedFormat, glFormatInfo.glSuppliedFormatType, pixelData);
}
else if (hostTexture->dim == Latte::E_DIM::DIM_CUBEMAP)
{
if (glFormatInfo.glIsCompressed)
glCompressedTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mipIndex, 0, 0, sliceIndex, width, height, 1, glFormatInfo.glInternalFormat, imageSize, pixelData);
else
glTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mipIndex, 0, 0, sliceIndex, width, height, 1, glFormatInfo.glSuppliedFormat, glFormatInfo.glSuppliedFormatType, pixelData);
}
else
{
cemu_assert_debug(false);
glTextureSubImage3DWrapper(hostTexture->glTexTarget, hostTexture->glId_texture, mipIndex, 0, 0, sliceIndex, effectiveWidth, effectiveHeight, 1, glFormatInfo.glSuppliedFormat, glFormatInfo.glSuppliedFormatType, pixelData);
}
catchOpenGLError();
}
// use persistent buffers to upload data
void OpenGLRenderer_texture_loadSlice_viaBuffers(LatteTexture* hostTexture, sint32 width, sint32 height, sint32 depth, void* pixelData, sint32 sliceIndex, sint32 mipIndex, uint32 imageSize)
{
@ -1220,10 +1197,10 @@ void OpenGLRenderer::texture_clearSlice(LatteTexture* hostTextureGeneric, sint32
glClearTexSubImage(hostTexture->glId_texture, mipIndex, 0, 0, sliceIndex, effectiveWidth, effectiveHeight, 1, formatInfoGL.glSuppliedFormat, formatInfoGL.glSuppliedFormatType, NULL);
}
LatteTexture* OpenGLRenderer::texture_createTextureEx(uint32 textureUnit, Latte::E_DIM dim, MPTR physAddress, MPTR physMipAddress, Latte::E_GX2SURFFMT format, uint32 width, uint32 height, uint32 depth, uint32 pitch, uint32 mipLevels,
LatteTexture* OpenGLRenderer::texture_createTextureEx(Latte::E_DIM dim, MPTR physAddress, MPTR physMipAddress, Latte::E_GX2SURFFMT format, uint32 width, uint32 height, uint32 depth, uint32 pitch, uint32 mipLevels,
uint32 swizzle, Latte::E_HWTILEMODE tileMode, bool isDepth)
{
return new LatteTextureGL(textureUnit, dim, physAddress, physMipAddress, format, width, height, depth, pitch, mipLevels, swizzle, tileMode, isDepth);
return new LatteTextureGL(dim, physAddress, physMipAddress, format, width, height, depth, pitch, mipLevels, swizzle, tileMode, isDepth);
}
@ -1239,42 +1216,18 @@ void OpenGLRenderer::texture_setActiveTextureUnit(sint32 index)
void OpenGLRenderer::texture_bindAndActivate(LatteTextureView* textureView, uint32 textureUnit)
{
const auto textureViewGL = (LatteTextureViewGL*)textureView;
cemu_assert_debug(textureUnit < (sizeof(LatteBoundTexturesBackup) / sizeof(LatteBoundTexturesBackup[0])));
// don't call glBindTexture if the texture is already bound
if (LatteBoundTextures[textureUnit] == textureViewGL)
if (m_latteBoundTextures[textureUnit] == textureViewGL)
{
texture_setActiveTextureUnit(textureUnit);
return; // already bound
}
// bind
LatteBoundTextures[textureUnit] = textureViewGL;
m_latteBoundTextures[textureUnit] = textureViewGL;
texture_setActiveTextureUnit(textureUnit);
if (textureViewGL)
{
glBindTexture(textureViewGL->glTexTarget, textureViewGL->glTexId);
texUnitTexId[textureUnit] = textureViewGL->glTexId;
texUnitTexTarget[textureUnit] = textureViewGL->glTexTarget;
}
}
void OpenGLRenderer::texture_bindAndActivateRawTex(LatteTexture* texture, uint32 textureUnit)
{
cemu_assert_debug(textureUnit < (sizeof(LatteBoundTexturesBackup) / sizeof(LatteBoundTexturesBackup[0])));
// don't call glBindTexture if the texture is already bound
if (LatteBoundTextures[textureUnit] == texture)
{
texture_setActiveTextureUnit(textureUnit);
return; // already bound
}
// bind
LatteBoundTextures[textureUnit] = texture;
texture_setActiveTextureUnit(textureUnit);
if (texture)
{
auto textureGL = (LatteTextureGL*)texture;
glBindTexture(textureGL->glTexTarget, textureGL->glId_texture);
texUnitTexId[textureUnit] = textureGL->glId_texture;
texUnitTexTarget[textureUnit] = textureGL->glTexTarget;
}
}
@ -1282,18 +1235,18 @@ void OpenGLRenderer::texture_notifyDelete(LatteTextureView* textureView)
{
for (uint32 i = 0; i < Latte::GPU_LIMITS::NUM_TEXTURES_PER_STAGE * 3; i++)
{
if (LatteBoundTextures[i] == textureView)
LatteBoundTextures[i] = nullptr;
if (m_latteBoundTextures[i] == textureView)
m_latteBoundTextures[i] = nullptr;
}
}
// similar to _bindAndActivate() but doesn't call _setActiveTextureUnit() if texture is already bound
void OpenGLRenderer::texture_bindOnly(LatteTextureView* textureView1, uint32 textureUnit)
// set Latte texture, on the OpenGL renderer this behaves like _bindAndActivate() but doesn't call _setActiveTextureUnit() if the texture is already bound
void OpenGLRenderer::texture_setLatteTexture(LatteTextureView* textureView1, uint32 textureUnit)
{
auto textureView = ((LatteTextureViewGL*)textureView1);
cemu_assert_debug(textureUnit < Latte::GPU_LIMITS::NUM_TEXTURES_PER_STAGE * 3);
if (LatteBoundTextures[textureUnit] == textureView)
if (m_latteBoundTextures[textureUnit] == textureView)
return;
if (textureView == nullptr)
return;
@ -1301,45 +1254,17 @@ void OpenGLRenderer::texture_bindOnly(LatteTextureView* textureView1, uint32 tex
if (glBindTextureUnit)
{
glBindTextureUnit(textureUnit, textureView->glTexId);
LatteBoundTextures[textureUnit] = textureView;
texUnitTexId[textureUnit] = textureView->glTexId;
texUnitTexTarget[textureUnit] = textureView->glTexTarget;
m_latteBoundTextures[textureUnit] = textureView;
activeTextureUnit = -1;
}
else
{
texture_setActiveTextureUnit(textureUnit);
glBindTexture(textureView->glTexTarget, textureView->glTexId);
LatteBoundTextures[textureUnit] = textureView;
texUnitTexId[textureUnit] = textureView->glTexId;
texUnitTexTarget[textureUnit] = textureView->glTexTarget;
m_latteBoundTextures[textureUnit] = textureView;
}
}
void OpenGLRenderer::texture_rememberBoundTexture(uint32 textureUnit)
{
cemu_assert_debug(texUnitBackupSlotUsed[textureUnit] == false);
texUnitBackupSlotUsed[textureUnit] = true;
LatteBoundTexturesBackup[textureUnit] = LatteBoundTextures[textureUnit];
texUnitTexIdBackup[textureUnit] = texUnitTexId[textureUnit];
texUnitTexTargetBackup[textureUnit] = texUnitTexTarget[textureUnit];
}
void OpenGLRenderer::texture_restoreBoundTexture(uint32 textureUnit)
{
cemu_assert_debug(texUnitBackupSlotUsed[textureUnit] == true);
texUnitBackupSlotUsed[textureUnit] = false;
if (LatteBoundTextures[textureUnit] == LatteBoundTexturesBackup[textureUnit])
{
return; // already bound
}
LatteBoundTextures[textureUnit] = LatteBoundTexturesBackup[textureUnit];
texUnitTexId[textureUnit] = texUnitTexIdBackup[textureUnit];
texUnitTexTarget[textureUnit] = texUnitTexTargetBackup[textureUnit];
texture_setActiveTextureUnit(textureUnit);
glBindTexture(texUnitTexTargetBackup[textureUnit], texUnitTexIdBackup[textureUnit]);
}
void OpenGLRenderer::texture_copyImageSubData(LatteTexture* src, sint32 srcMip, sint32 effectiveSrcX, sint32 effectiveSrcY, sint32 srcSlice, LatteTexture* dst, sint32 dstMip, sint32 effectiveDstX, sint32 effectiveDstY,
sint32 dstSlice, sint32 effectiveCopyWidth, sint32 effectiveCopyHeight, sint32 srcDepth)
{

View File

@ -79,13 +79,10 @@ public:
void texture_clearColorSlice(LatteTexture* hostTexture, sint32 sliceIndex, sint32 mipIndex, float r, float g, float b, float a) override;
void texture_clearDepthSlice(LatteTexture* hostTexture, uint32 sliceIndex, sint32 mipIndex, bool clearDepth, bool clearStencil, float depthValue, uint32 stencilValue) override;
LatteTexture* texture_createTextureEx(uint32 textureUnit, Latte::E_DIM dim, MPTR physAddress, MPTR physMipAddress, Latte::E_GX2SURFFMT format, uint32 width, uint32 height, uint32 depth, uint32 pitch, uint32 mipLevels, uint32 swizzle, Latte::E_HWTILEMODE tileMode, bool isDepth) override;
LatteTexture* texture_createTextureEx(Latte::E_DIM dim, MPTR physAddress, MPTR physMipAddress, Latte::E_GX2SURFFMT format, uint32 width, uint32 height, uint32 depth, uint32 pitch, uint32 mipLevels, uint32 swizzle, Latte::E_HWTILEMODE tileMode, bool isDepth) override;
void texture_bindAndActivate(LatteTextureView* textureView, uint32 textureUnit) override;
void texture_bindAndActivateRawTex(LatteTexture* texture, uint32 textureUnit) override;
void texture_bindOnly(LatteTextureView* textureView, uint32 textureUnit) override;
void texture_rememberBoundTexture(uint32 textureUnit) override;
void texture_restoreBoundTexture(uint32 textureUnit) override;
void texture_setLatteTexture(LatteTextureView* textureView, uint32 textureUnit) override;
void texture_bindAndActivate(LatteTextureView* textureView, uint32 textureUnit);
void texture_copyImageSubData(LatteTexture* src, sint32 srcMip, sint32 effectiveSrcX, sint32 effectiveSrcY, sint32 srcSlice, LatteTexture* dst, sint32 dstMip, sint32 effectiveDstX, sint32 effectiveDstY, sint32 dstSlice, sint32 effectiveCopyWidth, sint32 effectiveCopyHeight, sint32 srcDepth) override;
void texture_notifyDelete(LatteTextureView* textureView);
@ -188,14 +185,7 @@ private:
bool m_isXfbActive = false;
sint32 activeTextureUnit = 0;
void* LatteBoundTextures[Latte::GPU_LIMITS::NUM_TEXTURES_PER_STAGE * 3]{};
GLuint texUnitTexId[Latte::GPU_LIMITS::NUM_TEXTURES_PER_STAGE * 3]{};
GLenum texUnitTexTarget[Latte::GPU_LIMITS::NUM_TEXTURES_PER_STAGE * 3]{};
void* LatteBoundTexturesBackup[Latte::GPU_LIMITS::NUM_TEXTURES_PER_STAGE * 3]{};
GLuint texUnitTexIdBackup[Latte::GPU_LIMITS::NUM_TEXTURES_PER_STAGE * 3]{};
GLenum texUnitTexTargetBackup[Latte::GPU_LIMITS::NUM_TEXTURES_PER_STAGE * 3]{};
bool texUnitBackupSlotUsed[Latte::GPU_LIMITS::NUM_TEXTURES_PER_STAGE * 3]{};
void* m_latteBoundTextures[Latte::GPU_LIMITS::NUM_TEXTURES_PER_STAGE * 3]{};
// attribute stream
GLuint glAttributeCacheAB{};

View File

@ -1342,7 +1342,7 @@ uint32 _correctTextureCompSelGL(Latte::E_GX2SURFFMT format, uint32 compSel)
return compSel;
}
#define quickBindTexture() if( textureIsActive == false ) { g_renderer->texture_bindAndActivate(hostTextureView, hostTextureUnit); textureIsActive = true; }
#define quickBindTexture() if( textureIsActive == false ) { texture_bindAndActivate(hostTextureView, hostTextureUnit); textureIsActive = true; }
uint32 _getGLMinFilter(Latte::LATTE_SQ_TEX_SAMPLER_WORD0_0::E_XY_FILTER filterMin, Latte::LATTE_SQ_TEX_SAMPLER_WORD0_0::E_Z_FILTER filterMip)
{
@ -1365,11 +1365,9 @@ uint32 _getGLMinFilter(Latte::LATTE_SQ_TEX_SAMPLER_WORD0_0::E_XY_FILTER filterMi
/*
* Update channel swizzling and other texture settings for a texture unit
* hostTextureView is the texture unit view used on the host side
* The baseGX2TexUnit parameter is used to identify the shader stage in which this texture is accessed
*/
void OpenGLRenderer::renderstate_updateTextureSettingsGL(LatteDecompilerShader* shaderContext, LatteTextureView* _hostTextureView, uint32 hostTextureUnit, const Latte::LATTE_SQ_TEX_RESOURCE_WORD4_N texUnitWord4, uint32 texUnitIndex, bool isDepthSampler)
{
// todo - this is OpenGL-specific, decouple this from the renderer-neutral backend
auto hostTextureView = (LatteTextureViewGL*)_hostTextureView;
LatteTexture* baseTexture = hostTextureView->baseTexture;

View File

@ -52,7 +52,7 @@ void OpenGLRenderer::surfaceCopy_copySurfaceWithFormatConversion(LatteTexture* s
LatteTextureView* sourceView = sourceTexture->GetOrCreateView(srcMip, 1, srcSlice, 1);
LatteTextureView* destinationView = destinationTexture->GetOrCreateView(dstMip, 1, dstSlice, 1);
g_renderer->texture_bindAndActivate(sourceView, 0);
texture_bindAndActivate(sourceView, 0);
catchOpenGLError();
// setup texture attributes
_setDepthCompareMode((LatteTextureViewGL*)sourceView, 0);

View File

@ -1,4 +1,5 @@
#include "Cafe/HW/Latte/Renderer/Renderer.h"
#include "Cafe/HW/Latte/Renderer/OpenGL/OpenGLRenderer.h"
#include "Cafe/HW/Latte/Renderer/OpenGL/OpenGLTextureReadback.h"
#include "Cafe/HW/Latte/Renderer/OpenGL/LatteTextureViewGL.h"
@ -93,8 +94,7 @@ LatteTextureReadbackInfoGL::~LatteTextureReadbackInfoGL()
void LatteTextureReadbackInfoGL::StartTransfer()
{
cemu_assert(m_textureView);
g_renderer->texture_bindAndActivate(m_textureView, 0);
((OpenGLRenderer*)g_renderer.get())->texture_bindAndActivate(m_textureView, 0);
// create unsynchronized buffer
glGenBuffers(1, &texImageBufferGL);
glBindBuffer(GL_PIXEL_PACK_BUFFER, texImageBufferGL);

View File

@ -110,13 +110,9 @@ public:
virtual void texture_clearColorSlice(LatteTexture* hostTexture, sint32 sliceIndex, sint32 mipIndex, float r, float g, float b, float a) = 0;
virtual void texture_clearDepthSlice(LatteTexture* hostTexture, uint32 sliceIndex, sint32 mipIndex, bool clearDepth, bool clearStencil, float depthValue, uint32 stencilValue) = 0;
virtual LatteTexture* texture_createTextureEx(uint32 textureUnit, Latte::E_DIM dim, MPTR physAddress, MPTR physMipAddress, Latte::E_GX2SURFFMT format, uint32 width, uint32 height, uint32 depth, uint32 pitch, uint32 mipLevels, uint32 swizzle, Latte::E_HWTILEMODE tileMode, bool isDepth) = 0;
virtual LatteTexture* texture_createTextureEx(Latte::E_DIM dim, MPTR physAddress, MPTR physMipAddress, Latte::E_GX2SURFFMT format, uint32 width, uint32 height, uint32 depth, uint32 pitch, uint32 mipLevels, uint32 swizzle, Latte::E_HWTILEMODE tileMode, bool isDepth) = 0;
virtual void texture_bindAndActivate(LatteTextureView* textureView, uint32 textureUnit) = 0;
virtual void texture_bindAndActivateRawTex(LatteTexture* texture, uint32 textureUnit) = 0;
virtual void texture_bindOnly(LatteTextureView* textureView, uint32 textureUnit) = 0;
virtual void texture_rememberBoundTexture(uint32 textureUnit) = 0;
virtual void texture_restoreBoundTexture(uint32 textureUnit) = 0;
virtual void texture_setLatteTexture(LatteTextureView* textureView, uint32 textureUnit) = 0;
virtual void texture_copyImageSubData(LatteTexture* src, sint32 srcMip, sint32 effectiveSrcX, sint32 effectiveSrcY, sint32 srcSlice, LatteTexture* dst, sint32 dstMip, sint32 effectiveDstX, sint32 effectiveDstY, sint32 dstSlice, sint32 effectiveCopyWidth, sint32 effectiveCopyHeight, sint32 srcDepth) = 0;
virtual LatteTextureReadbackInfo* texture_createReadback(LatteTextureView* textureView) = 0;

View File

@ -3,9 +3,9 @@
#include "Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h"
#include "Cafe/HW/Latte/Renderer/Vulkan/VulkanAPI.h"
LatteTextureVk::LatteTextureVk(class VulkanRenderer* vkRenderer, uint32 textureUnit, Latte::E_DIM dim, MPTR physAddress, MPTR physMipAddress, Latte::E_GX2SURFFMT format, uint32 width, uint32 height, uint32 depth, uint32 pitch, uint32 mipLevels, uint32 swizzle,
LatteTextureVk::LatteTextureVk(class VulkanRenderer* vkRenderer, Latte::E_DIM dim, MPTR physAddress, MPTR physMipAddress, Latte::E_GX2SURFFMT format, uint32 width, uint32 height, uint32 depth, uint32 pitch, uint32 mipLevels, uint32 swizzle,
Latte::E_HWTILEMODE tileMode, bool isDepth)
: LatteTexture(textureUnit, dim, physAddress, physMipAddress, format, width, height, depth, pitch, mipLevels, swizzle, tileMode, isDepth), m_vkr(vkRenderer)
: LatteTexture(dim, physAddress, physMipAddress, format, width, height, depth, pitch, mipLevels, swizzle, tileMode, isDepth), m_vkr(vkRenderer)
{
vkObjTex = new VKRObjectTexture();

View File

@ -9,7 +9,7 @@
class LatteTextureVk : public LatteTexture
{
public:
LatteTextureVk(class VulkanRenderer* vkRenderer, uint32 textureUnit, Latte::E_DIM dim, MPTR physAddress, MPTR physMipAddress, Latte::E_GX2SURFFMT format, uint32 width, uint32 height, uint32 depth, uint32 pitch, uint32 mipLevels,
LatteTextureVk(class VulkanRenderer* vkRenderer, Latte::E_DIM dim, MPTR physAddress, MPTR physMipAddress, Latte::E_GX2SURFFMT format, uint32 width, uint32 height, uint32 depth, uint32 pitch, uint32 mipLevels,
uint32 swizzle, Latte::E_HWTILEMODE tileMode, bool isDepth);
~LatteTextureVk();

View File

@ -3326,18 +3326,13 @@ void VulkanRenderer::texture_loadSlice(LatteTexture* hostTexture, sint32 width,
barrier_image<ANY_TRANSFER, ANY_TRANSFER | IMAGE_READ | IMAGE_WRITE>(vkTexture, barrierSubresourceRange, VK_IMAGE_LAYOUT_GENERAL);
}
LatteTexture* VulkanRenderer::texture_createTextureEx(uint32 textureUnit, Latte::E_DIM dim, MPTR physAddress, MPTR physMipAddress, Latte::E_GX2SURFFMT format, uint32 width, uint32 height, uint32 depth, uint32 pitch, uint32 mipLevels,
LatteTexture* VulkanRenderer::texture_createTextureEx(Latte::E_DIM dim, MPTR physAddress, MPTR physMipAddress, Latte::E_GX2SURFFMT format, uint32 width, uint32 height, uint32 depth, uint32 pitch, uint32 mipLevels,
uint32 swizzle, Latte::E_HWTILEMODE tileMode, bool isDepth)
{
return new LatteTextureVk(this, textureUnit, dim, physAddress, physMipAddress, format, width, height, depth, pitch, mipLevels, swizzle, tileMode, isDepth);
return new LatteTextureVk(this, dim, physAddress, physMipAddress, format, width, height, depth, pitch, mipLevels, swizzle, tileMode, isDepth);
}
void VulkanRenderer::texture_bindAndActivate(LatteTextureView* textureView, uint32 textureUnit)
{
m_state.boundTexture[textureUnit] = static_cast<LatteTextureViewVk*>(textureView);
}
void VulkanRenderer::texture_bindOnly(LatteTextureView* textureView, uint32 textureUnit)
void VulkanRenderer::texture_setLatteTexture(LatteTextureView* textureView, uint32 textureUnit)
{
m_state.boundTexture[textureUnit] = static_cast<LatteTextureViewVk*>(textureView);
}

View File

@ -300,15 +300,10 @@ public:
void texture_loadSlice(LatteTexture* hostTexture, sint32 width, sint32 height, sint32 depth, void* pixelData, sint32 sliceIndex, sint32 mipIndex, uint32 compressedImageSize) override;
LatteTexture* texture_createTextureEx(uint32 textureUnit, Latte::E_DIM dim, MPTR physAddress, MPTR physMipAddress, Latte::E_GX2SURFFMT format, uint32 width, uint32 height, uint32 depth, uint32 pitch, uint32 mipLevels, uint32 swizzle, Latte::E_HWTILEMODE tileMode, bool isDepth) override;
LatteTexture* texture_createTextureEx(Latte::E_DIM dim, MPTR physAddress, MPTR physMipAddress, Latte::E_GX2SURFFMT format, uint32 width, uint32 height, uint32 depth, uint32 pitch, uint32 mipLevels, uint32 swizzle, Latte::E_HWTILEMODE tileMode, bool isDepth) override;
void texture_bindAndActivate(LatteTextureView* textureView, uint32 textureUnit) override;
void texture_bindOnly(LatteTextureView* textureView, uint32 textureUnit) override;
void texture_setLatteTexture(LatteTextureView* textureView, uint32 textureUnit) override;
void texture_bindAndActivateRawTex(LatteTexture* texture, uint32 textureUnit) override {};
void texture_rememberBoundTexture(uint32 textureUnit) override {};
void texture_restoreBoundTexture(uint32 textureUnit) override {};
void texture_copyImageSubData(LatteTexture* src, sint32 srcMip, sint32 effectiveSrcX, sint32 effectiveSrcY, sint32 srcSlice, LatteTexture* dst, sint32 dstMip, sint32 effectiveDstX, sint32 effectiveDstY, sint32 dstSlice, sint32 effectiveCopyWidth, sint32 effectiveCopyHeight, sint32 srcDepth) override;
LatteTextureReadbackInfo* texture_createReadback(LatteTextureView* textureView) override;

View File

@ -42,6 +42,177 @@ typedef struct __GLXFBConfigRec *GLXFBConfig;
#undef GLFUNC
#undef EGLFUNC
// DSA-style helpers with fallback to legacy API if DSA is not supported
#define DSA_FORCE_DISABLE false // set to true to simulate DSA not being supported
static GLenum GetGLBindingFromTextureTarget(GLenum texTarget)
{
switch(texTarget)
{
case GL_TEXTURE_1D: return GL_TEXTURE_BINDING_1D;
case GL_TEXTURE_2D: return GL_TEXTURE_BINDING_2D;
case GL_TEXTURE_3D: return GL_TEXTURE_BINDING_3D;
case GL_TEXTURE_2D_ARRAY: return GL_TEXTURE_BINDING_2D_ARRAY;
case GL_TEXTURE_CUBE_MAP: return GL_TEXTURE_BINDING_CUBE_MAP;
case GL_TEXTURE_CUBE_MAP_ARRAY: return GL_TEXTURE_BINDING_CUBE_MAP_ARRAY;
default:
cemu_assert_unimplemented();
return 0;
}
}
static GLuint glCreateTextureWrapper(GLenum target)
{
GLuint tex;
if (glCreateTextures && !DSA_FORCE_DISABLE)
{
glCreateTextures(target, 1, &tex);
return tex;
}
GLint originalTexture;
glGetIntegerv(GetGLBindingFromTextureTarget(target), &originalTexture);
glGenTextures(1, &tex);
glBindTexture(target, tex);
glBindTexture(target, originalTexture);
return tex;
}
static void glTextureStorage1DWrapper(GLenum target, GLuint texture, GLsizei levels, GLenum internalformat, GLsizei width)
{
if (glTextureStorage1D && !DSA_FORCE_DISABLE)
{
glTextureStorage1D(texture, levels, internalformat, width);
return;
}
GLenum binding = GetGLBindingFromTextureTarget(target);
GLint originalTexture;
glGetIntegerv(binding, &originalTexture);
glBindTexture(target, texture);
glTexStorage1D(target, levels, internalformat, width);
glBindTexture(target, originalTexture);
}
static void glTextureStorage2DWrapper(GLenum target, GLuint texture, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height)
{
if (glTextureStorage2D && !DSA_FORCE_DISABLE)
{
glTextureStorage2D(texture, levels, internalformat, width, height);
return;
}
GLenum binding = GetGLBindingFromTextureTarget(target);
GLint originalTexture;
glGetIntegerv(binding, &originalTexture);
glBindTexture(target, texture);
glTexStorage2D(target, levels, internalformat, width, height);
glBindTexture(target, originalTexture);
}
static void glTextureStorage3DWrapper(GLenum target, GLuint texture, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)
{
if (glTextureStorage3D && !DSA_FORCE_DISABLE)
{
glTextureStorage3D(texture, levels, internalformat, width, height, depth);
return;
}
GLenum binding = GetGLBindingFromTextureTarget(target);
GLint originalTexture;
glGetIntegerv(binding, &originalTexture);
glBindTexture(target, texture);
glTexStorage3D(target, levels, internalformat, width, height, depth);
glBindTexture(target, originalTexture);
}
static void glTextureSubImage1DWrapper(GLenum target, GLuint texture, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void* pixels)
{
if (glTextureSubImage1D && !DSA_FORCE_DISABLE)
{
glTextureSubImage1D(texture, level, xoffset, width, format, type, pixels);
return;
}
GLenum binding = GetGLBindingFromTextureTarget(target);
GLint originalTexture;
glGetIntegerv(binding, &originalTexture);
glBindTexture(target, texture);
glTexSubImage1D(target, level, xoffset, width, format, type, pixels);
glBindTexture(target, originalTexture);
}
static void glCompressedTextureSubImage1DWrapper(GLenum target, GLuint texture, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void* data)
{
if (glCompressedTextureSubImage1D && !DSA_FORCE_DISABLE)
{
glCompressedTextureSubImage1D(texture, level, xoffset, width, format, imageSize, data);
return;
}
GLenum binding = GetGLBindingFromTextureTarget(target);
GLint originalTexture;
glGetIntegerv(binding, &originalTexture);
glBindTexture(target, texture);
glCompressedTexSubImage1D(target, level, xoffset, width, format, imageSize, data);
glBindTexture(target, originalTexture);
}
static void glTextureSubImage2DWrapper(GLenum target, GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* pixels)
{
if (glTextureSubImage2D && !DSA_FORCE_DISABLE)
{
glTextureSubImage2D(texture, level, xoffset, yoffset, width, height, format, type, pixels);
return;
}
GLenum binding = GetGLBindingFromTextureTarget(target);
GLint originalTexture;
glGetIntegerv(binding, &originalTexture);
glBindTexture(target, texture);
glTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels);
glBindTexture(target, originalTexture);
}
static void glCompressedTextureSubImage2DWrapper(GLenum target, GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data)
{
if (glCompressedTextureSubImage2D && !DSA_FORCE_DISABLE)
{
glCompressedTextureSubImage2D(texture, level, xoffset, yoffset, width, height, format, imageSize, data);
return;
}
GLenum binding = GetGLBindingFromTextureTarget(target);
GLint originalTexture;
glGetIntegerv(binding, &originalTexture);
glBindTexture(target, texture);
glCompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, imageSize, data);
glBindTexture(target, originalTexture);
}
static void glTextureSubImage3DWrapper(GLenum target, GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* pixels)
{
if(glTextureSubImage3D && !DSA_FORCE_DISABLE)
{
glTextureSubImage3D(texture, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels);
return;
}
GLenum binding = GetGLBindingFromTextureTarget(target);
GLint originalTexture;
glGetIntegerv(binding, &originalTexture);
glBindTexture(target, texture);
glTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels);
glBindTexture(target, originalTexture);
}
static void glCompressedTextureSubImage3DWrapper(GLenum target, GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void* data)
{
if(glCompressedTextureSubImage3D && !DSA_FORCE_DISABLE)
{
glCompressedTextureSubImage3D(texture, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data);
return;
}
GLenum binding = GetGLBindingFromTextureTarget(target);
GLint originalTexture;
glGetIntegerv(binding, &originalTexture);
glBindTexture(target, texture);
glCompressedTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data);
glBindTexture(target, originalTexture);
}
// this prevents Windows GL.h from being included:
#define __gl_h_
#define __GL_H__

View File

@ -171,10 +171,13 @@ GLFUNC(PFNGLTEXSTORAGE2DPROC, glTexStorage2D)
GLFUNC(PFNGLTEXSTORAGE3DPROC, glTexStorage3D)
GLFUNC(PFNGLTEXIMAGE3DPROC, glTexImage3D)
GLFUNC(PFNGLTEXSUBIMAGE3DPROC, glTexSubImage3D)
GLFUNC(PFNGLCOMPRESSEDTEXIMAGE1DPROC, glCompressedTexImage1D)
GLFUNC(PFNGLCOMPRESSEDTEXIMAGE2DPROC, glCompressedTexImage2D)
GLFUNC(PFNGLCOMPRESSEDTEXIMAGE3DPROC, glCompressedTexImage3D)
GLFUNC(PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC, glCompressedTexSubImage1D)
GLFUNC(PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC, glCompressedTexSubImage2D)
GLFUNC(PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC, glCompressedTexSubImage3D)
GLFUNC(PFNGLCOMPRESSEDTEXTURESUBIMAGE1DPROC, glCompressedTextureSubImage1D)
GLFUNC(PFNGLCOMPRESSEDTEXTURESUBIMAGE2DPROC, glCompressedTextureSubImage2D)
GLFUNC(PFNGLCOMPRESSEDTEXTURESUBIMAGE3DPROC, glCompressedTextureSubImage3D)
GLFUNC(PFNGLCOPYIMAGESUBDATAPROC, glCopyImageSubData)
@ -184,12 +187,17 @@ GLFUNC(PFNGLINVALIDATETEXIMAGEPROC, glInvalidateTexImage)
// texture DSA
GLFUNC(PFNGLCREATETEXTURESPROC, glCreateTextures)
GLFUNC(PFNGLBINDTEXTUREUNITPROC, glBindTextureUnit)
GLFUNC(PFNGLGETTEXTURELEVELPARAMETERIVPROC, glGetTextureLevelParameteriv)
GLFUNC(PFNGLTEXTUREPARAMETERIPROC, glTextureParameteri)
GLFUNC(PFNGLGETTEXTURESUBIMAGEPROC, glGetTextureSubImage)
GLFUNC(PFNGLTEXTURESUBIMAGE1DPROC, glTextureSubImage1D)
GLFUNC(PFNGLTEXTURESUBIMAGE2DPROC, glTextureSubImage2D);
GLFUNC(PFNGLTEXTURESUBIMAGE3DPROC, glTextureSubImage3D)
GLFUNC(PFNGLTEXTURESTORAGE1DPROC, glTextureStorage1D)
GLFUNC(PFNGLTEXTURESTORAGE2DPROC, glTextureStorage2D)
GLFUNC(PFNGLTEXTURESTORAGE3DPROC, glTextureStorage3D)
// instancing / draw