diff --git a/src/Cafe/HW/Latte/Renderer/Common/CommonRendererCore.cpp b/src/Cafe/HW/Latte/Renderer/Common/CommonRendererCore.cpp index 4a5de6b3..a8a26eb4 100644 --- a/src/Cafe/HW/Latte/Renderer/Common/CommonRendererCore.cpp +++ b/src/Cafe/HW/Latte/Renderer/Common/CommonRendererCore.cpp @@ -1,4 +1,12 @@ #include "CommonRendererCore.h" +#include "Cafe/HW/Latte/Renderer/Renderer.h" +#include "Cafe/HW/Latte/ISA/RegDefines.h" +#include "config/CemuConfig.h" + +#ifdef ENABLE_OPENGL +#include "Common/GLInclude/glFunctions.h" +#include "Cafe/HW/Latte/Renderer/OpenGL/LatteTextureViewGL.h" +#endif indexState_t indexState = { 0 }; AttributePointerCacheEntry_t activeAttributePointer[LATTE_VS_ATTRIBUTE_LIMIT] = { 0 }; @@ -8,54 +16,35 @@ indexDataCacheEntry2_t* indexDataCacheFirst = nullptr; // points to least recent indexDataCacheEntry2_t* indexDataCacheLast = nullptr; // points to most recently used item sint32 indexDataCacheEntryCount = 0; -uint8* CommonRenderer_getAttributePointerCacheVboOutput(uint32 attributeShaderLoc) +void CommonRenderer_resetAttributePointerCache() { - return activeAttributePointer[attributeShaderLoc].vboOutput; + for (sint32 i = 0; i < LATTE_VS_ATTRIBUTE_LIMIT; i++) + { + activeAttributePointer[i].vboOutput = (uint8*)-1; + activeAttributePointer[i].vboStride = (uint32)-1; + } } -void CommonRenderer_setAttributePointerCacheVboOutput(uint32 attributeShaderLoc, uint8* vboOutput) +bool CommonRenderer_checkIfAttributePointerCacheChanged(uint32 attributeShaderLoc, uint8* vboOutput, uint32 vboStride, uint8 dataFormat, uint8 nfa, bool isSigned) { + // don't call glVertexAttribPointer if parameters have not changed + if ( + activeAttributePointer[attributeShaderLoc].vboOutput == vboOutput && + activeAttributePointer[attributeShaderLoc].vboStride == vboStride && + activeAttributePointer[attributeShaderLoc].dataFormat == dataFormat && + activeAttributePointer[attributeShaderLoc].nfa == nfa && + activeAttributePointer[attributeShaderLoc].isSigned == isSigned + ) + { + return false; + } activeAttributePointer[attributeShaderLoc].vboOutput = vboOutput; -} - -uint32 CommonRenderer_getAttributePointerCacheVboStride(uint32 attributeShaderLoc) -{ - return activeAttributePointer[attributeShaderLoc].vboStride; -} - -void CommonRenderer_setAttributePointerCacheVboStride(uint32 attributeShaderLoc, uint32 vboStride) -{ activeAttributePointer[attributeShaderLoc].vboStride = vboStride; -} - -uint8 CommonRenderer_getAttributePointerCacheDataFormat(uint32 attributeShaderLoc) -{ - return activeAttributePointer[attributeShaderLoc].dataFormat; -} - -void CommonRenderer_setAttributePointerCacheDataFormat(uint32 attributeShaderLoc, uint8 dataFormat) -{ activeAttributePointer[attributeShaderLoc].dataFormat = dataFormat; -} - -uint8 CommonRenderer_getAttributePointerCacheNfa(uint32 attributeShaderLoc) -{ - return activeAttributePointer[attributeShaderLoc].nfa; -} - -void CommonRenderer_setAttributePointerCacheNfa(uint32 attributeShaderLoc, uint8 nfa) -{ activeAttributePointer[attributeShaderLoc].nfa = nfa; -} - -bool CommonRenderer_getAttributePointerCacheIsSigned(uint32 attributeShaderLoc) -{ - return activeAttributePointer[attributeShaderLoc].isSigned; -} - -void CommonRenderer_setAttributePointerCacheIsSigned(uint32 attributeShaderLoc, bool isSigned) -{ activeAttributePointer[attributeShaderLoc].isSigned = isSigned; + + return true; } indexState_t* CommonRenderer_getIndexState() @@ -152,4 +141,74 @@ void LatteDraw_cleanupAfterFrame() CommonRenderer_removeFromBucket(entry); free(entry); } +} + + +void LatteDraw_handleSpecialState8_clearAsDepth() +{ + if (LatteGPUState.contextNew.GetSpecialStateValues()[0] == 0) + cemuLog_logDebug(LogType::Force, "Special state 8 requires special state 0 but it is not set?"); + // get depth buffer information + uint32 regDepthBuffer = LatteGPUState.contextRegister[mmDB_HTILE_DATA_BASE]; + uint32 regDepthSize = LatteGPUState.contextRegister[mmDB_DEPTH_SIZE]; + uint32 regDepthBufferInfo = LatteGPUState.contextRegister[mmDB_DEPTH_INFO]; + // get format and tileMode from info reg + uint32 depthBufferTileMode = (regDepthBufferInfo >> 15) & 0xF; + + MPTR depthBufferPhysMem = regDepthBuffer << 8; + uint32 depthBufferPitch = (((regDepthSize >> 0) & 0x3FF) + 1); + uint32 depthBufferHeight = ((((regDepthSize >> 10) & 0xFFFFF) + 1) / depthBufferPitch); + depthBufferPitch <<= 3; + depthBufferHeight <<= 3; + uint32 depthBufferWidth = depthBufferPitch; + + sint32 sliceIndex = 0; // todo + sint32 mipIndex = 0; + + // clear all color buffers that match the format of the depth buffer + sint32 searchIndex = 0; + bool targetFound = false; + while (true) + { + LatteTextureView* view = LatteTC_LookupTextureByData(depthBufferPhysMem, depthBufferWidth, depthBufferHeight, depthBufferPitch, 0, 1, sliceIndex, 1, &searchIndex); + if (!view) + { + // should we clear in RAM instead? + break; + } + sint32 effectiveClearWidth = view->baseTexture->width; + sint32 effectiveClearHeight = view->baseTexture->height; + LatteTexture_scaleToEffectiveSize(view->baseTexture, &effectiveClearWidth, &effectiveClearHeight, 0); + + // hacky way to get clear color + float* regClearColor = (float*)(LatteGPUState.contextRegister + 0xC000 + 0); // REG_BASE_ALU_CONST + + uint8 clearColor[4] = { 0 }; + clearColor[0] = (uint8)(regClearColor[0] * 255.0f); + clearColor[1] = (uint8)(regClearColor[1] * 255.0f); + clearColor[2] = (uint8)(regClearColor[2] * 255.0f); + clearColor[3] = (uint8)(regClearColor[3] * 255.0f); + + // todo - use fragment shader software emulation (evoke for one pixel) to determine clear color + // todo - dont clear entire slice, use effectiveClearWidth, effectiveClearHeight + + switch (g_renderer->GetType()) + { +#ifdef ENABLE_OPENGL + case RendererAPI::OpenGL: + { + //cemu_assert_debug(false); // implement g_renderer->texture_clearColorSlice properly for OpenGL renderer + if (glClearTexSubImage) + glClearTexSubImage(((LatteTextureViewGL*)view)->glTexId, mipIndex, 0, 0, 0, effectiveClearWidth, effectiveClearHeight, 1, GL_RGBA, GL_UNSIGNED_BYTE, clearColor); + } +#endif + default: + { + if (view->baseTexture->isDepth) + g_renderer->texture_clearDepthSlice(view->baseTexture, sliceIndex + view->firstSlice, mipIndex + view->firstMip, true, view->baseTexture->hasStencil, 0.0f, 0); + else + g_renderer->texture_clearColorSlice(view->baseTexture, sliceIndex + view->firstSlice, mipIndex + view->firstMip, clearColor[0], clearColor[1], clearColor[2], clearColor[3]); + } + } + } } \ No newline at end of file diff --git a/src/Cafe/HW/Latte/Renderer/Common/CommonRendererCore.h b/src/Cafe/HW/Latte/Renderer/Common/CommonRendererCore.h index e7a71d69..1866c30c 100644 --- a/src/Cafe/HW/Latte/Renderer/Common/CommonRendererCore.h +++ b/src/Cafe/HW/Latte/Renderer/Common/CommonRendererCore.h @@ -77,16 +77,9 @@ typedef struct _indexDataCacheEntry_t _indexDataCacheEntry_t* prevInMostRecentUsage; // points to element which was used less recently }indexDataCacheEntry2_t; -uint8* CommonRenderer_getAttributePointerCacheVboOutput(uint32 attributeShaderLoc); -void CommonRenderer_setAttributePointerCacheVboOutput(uint32 attributeShaderLoc, uint8* vboOutput); -uint32 CommonRenderer_getAttributePointerCacheVboStride(uint32 attributeShaderLoc); -void CommonRenderer_setAttributePointerCacheVboStride(uint32 attributeShaderLoc, uint32 vboStride); -uint8 CommonRenderer_getAttributePointerCacheDataFormat(uint32 attributeShaderLoc); -void CommonRenderer_setAttributePointerCacheDataFormat(uint32 attributeShaderLoc, uint8 dataFormat); -uint8 CommonRenderer_getAttributePointerCacheNfa(uint32 attributeShaderLoc); -void CommonRenderer_setAttributePointerCacheNfa(uint32 attributeShaderLoc, uint8 nfa); -bool CommonRenderer_getAttributePointerCacheIsSigned(uint32 attributeShaderLoc); -void CommonRenderer_setAttributePointerCacheIsSigned(uint32 attributeShaderLoc, bool isSigned); +void CommonRenderer_resetAttributePointerCache(); +bool CommonRenderer_checkIfAttributePointerCacheChanged(uint32 attributeShaderLoc, uint8* vboOutput, uint32 vboStride, uint8 dataFormat, uint8 nfa, bool isSigned); + indexState_t* CommonRenderer_getIndexState(); indexDataCacheEntry2_t** CommonRenderer_getIndexDataCacheFirst(); indexDataCacheEntry2_t** CommonRenderer_getIndexDataCacheBucket(uint32 bucketIdx); @@ -95,4 +88,5 @@ sint32* CommonRenderer_getIndexDataCacheEntryCount(); void CommonRenderer_appendToUsageLinkedList(indexDataCacheEntry2_t* entry); void CommonRenderer_removeFromUsageLinkedList(indexDataCacheEntry2_t* entry); void CommonRenderer_removeFromBucket(indexDataCacheEntry2_t* entry); -void LatteDraw_cleanupAfterFrame(); \ No newline at end of file +void LatteDraw_cleanupAfterFrame(); +void LatteDraw_handleSpecialState8_clearAsDepth(); \ No newline at end of file diff --git a/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.cpp b/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.cpp index 7ceaf74d..8c2da361 100644 --- a/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.cpp +++ b/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.cpp @@ -33,7 +33,7 @@ extern bool hasValidFramebufferAttached; float supportBufferData[512 * 4]; -// Defined in the OpenGL renderer +// Defined in the Common renderer void LatteDraw_handleSpecialState8_clearAsDepth(); std::vector MetalRenderer::GetDevices() diff --git a/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRendererCore.cpp b/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRendererCore.cpp index 19c4825d..94620cda 100644 --- a/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRendererCore.cpp +++ b/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRendererCore.cpp @@ -27,11 +27,7 @@ extern bool hasValidFramebufferAttached; void LatteDraw_resetAttributePointerCache() { - for (sint32 i = 0; i < LATTE_VS_ATTRIBUTE_LIMIT; i++) - { - CommonRenderer_setAttributePointerCacheVboOutput(i, (uint8*)-1); - CommonRenderer_setAttributePointerCacheVboStride(i, (uint32)-1); - } + CommonRenderer_resetAttributePointerCache(); } void _setAttributeBufferPointerRaw(uint32 attributeShaderLoc, uint8* buffer, uint32 bufferSize, uint32 stride, LatteParsedFetchShaderAttribute_t* attrib, uint8* vboOutput, uint32 vboStride) @@ -40,21 +36,11 @@ void _setAttributeBufferPointerRaw(uint32 attributeShaderLoc, uint8* buffer, uin bool isSigned = attrib->isSigned != 0; uint8 nfa = attrib->nfa; // don't call glVertexAttribIPointer if parameters have not changed - if ( - CommonRenderer_getAttributePointerCacheVboOutput(attributeShaderLoc) == vboOutput && - CommonRenderer_getAttributePointerCacheVboStride(attributeShaderLoc) == vboStride && - CommonRenderer_getAttributePointerCacheDataFormat(attributeShaderLoc) == dataFormat && - CommonRenderer_getAttributePointerCacheNfa(attributeShaderLoc) == nfa && - CommonRenderer_getAttributePointerCacheIsSigned(attributeShaderLoc) == isSigned - ) - { + bool attributePointerChanged = CommonRenderer_checkIfAttributePointerCacheChanged(attributeShaderLoc, vboOutput, vboStride, dataFormat, nfa, isSigned); + if (!attributePointerChanged) { return; } - CommonRenderer_setAttributePointerCacheVboOutput(attributeShaderLoc, vboOutput); - CommonRenderer_setAttributePointerCacheVboStride(attributeShaderLoc, vboStride); - CommonRenderer_setAttributePointerCacheDataFormat(attributeShaderLoc, dataFormat); - CommonRenderer_setAttributePointerCacheNfa(attributeShaderLoc, nfa); - CommonRenderer_setAttributePointerCacheIsSigned(attributeShaderLoc, isSigned); + // setup attribute pointer if (dataFormat == FMT_32_32_32_32_FLOAT || dataFormat == FMT_32_32_32_32) { @@ -385,70 +371,6 @@ void LatteDrawGL_prepareIndicesWithGPUCache(MPTR indexDataMPTR, _INDEX_TYPE inde indexState->indexData = (uint8*)(size_t)cacheEntry->heapEntry->startOffset; } -void LatteDraw_handleSpecialState8_clearAsDepth() -{ - if (LatteGPUState.contextNew.GetSpecialStateValues()[0] == 0) - cemuLog_logDebug(LogType::Force, "Special state 8 requires special state 0 but it is not set?"); - // get depth buffer information - uint32 regDepthBuffer = LatteGPUState.contextRegister[mmDB_HTILE_DATA_BASE]; - uint32 regDepthSize = LatteGPUState.contextRegister[mmDB_DEPTH_SIZE]; - uint32 regDepthBufferInfo = LatteGPUState.contextRegister[mmDB_DEPTH_INFO]; - // get format and tileMode from info reg - uint32 depthBufferTileMode = (regDepthBufferInfo >> 15) & 0xF; - - MPTR depthBufferPhysMem = regDepthBuffer << 8; - uint32 depthBufferPitch = (((regDepthSize >> 0) & 0x3FF) + 1); - uint32 depthBufferHeight = ((((regDepthSize >> 10) & 0xFFFFF) + 1) / depthBufferPitch); - depthBufferPitch <<= 3; - depthBufferHeight <<= 3; - uint32 depthBufferWidth = depthBufferPitch; - - sint32 sliceIndex = 0; // todo - sint32 mipIndex = 0; - - // clear all color buffers that match the format of the depth buffer - sint32 searchIndex = 0; - bool targetFound = false; - while (true) - { - LatteTextureView* view = LatteTC_LookupTextureByData(depthBufferPhysMem, depthBufferWidth, depthBufferHeight, depthBufferPitch, 0, 1, sliceIndex, 1, &searchIndex); - if (!view) - { - // should we clear in RAM instead? - break; - } - sint32 effectiveClearWidth = view->baseTexture->width; - sint32 effectiveClearHeight = view->baseTexture->height; - LatteTexture_scaleToEffectiveSize(view->baseTexture, &effectiveClearWidth, &effectiveClearHeight, 0); - - // hacky way to get clear color - float* regClearColor = (float*)(LatteGPUState.contextRegister + 0xC000 + 0); // REG_BASE_ALU_CONST - - uint8 clearColor[4] = { 0 }; - clearColor[0] = (uint8)(regClearColor[0] * 255.0f); - clearColor[1] = (uint8)(regClearColor[1] * 255.0f); - clearColor[2] = (uint8)(regClearColor[2] * 255.0f); - clearColor[3] = (uint8)(regClearColor[3] * 255.0f); - - // todo - use fragment shader software emulation (evoke for one pixel) to determine clear color - // todo - dont clear entire slice, use effectiveClearWidth, effectiveClearHeight - - if (g_renderer->GetType() == RendererAPI::OpenGL) - { - //cemu_assert_debug(false); // implement g_renderer->texture_clearColorSlice properly for OpenGL renderer - if (glClearTexSubImage) - glClearTexSubImage(((LatteTextureViewGL*)view)->glTexId, mipIndex, 0, 0, 0, effectiveClearWidth, effectiveClearHeight, 1, GL_RGBA, GL_UNSIGNED_BYTE, clearColor); - } - else - { - if (view->baseTexture->isDepth) - g_renderer->texture_clearDepthSlice(view->baseTexture, sliceIndex + view->firstSlice, mipIndex + view->firstMip, true, view->baseTexture->hasStencil, 0.0f, 0); - else - g_renderer->texture_clearColorSlice(view->baseTexture, sliceIndex + view->firstSlice, mipIndex + view->firstMip, clearColor[0], clearColor[1], clearColor[2], clearColor[3]); - } - } -} - void LatteDrawGL_doDraw(_INDEX_TYPE indexType, uint32 baseVertex, uint32 baseInstance, uint32 instanceCount, uint32 count) { indexState_t* indexState = CommonRenderer_getIndexState(); diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRendererCore.cpp b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRendererCore.cpp index a6814186..d0933e35 100644 --- a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRendererCore.cpp +++ b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRendererCore.cpp @@ -1221,6 +1221,7 @@ void VulkanRenderer::draw_endRenderPass() m_state.activeRenderpassFBO = nullptr; } +// Defined in the Common renderer void LatteDraw_handleSpecialState8_clearAsDepth(); // transfer depth buffer data to color buffer