Latte+Vulkan: More code tweaks for performance and cleanup

This commit is contained in:
Exzap 2026-06-15 19:57:36 +02:00
parent 377307515c
commit 309bca61b2
4 changed files with 17 additions and 35 deletions

View File

@ -70,8 +70,6 @@ void rectGenerate4thVertex(uint32be* output, uint32be* input0, uint32be* input1,
output[f] = _swapEndianU32(output[f]); output[f] = _swapEndianU32(output[f]);
} }
#define ATTRIBUTE_CACHE_RING_SIZE (128) // up to 128 entries can be cached
void LatteBufferCache_LoadRemappedUniforms(LatteDecompilerShader* shader, float* uniformData) void LatteBufferCache_LoadRemappedUniforms(LatteDecompilerShader* shader, float* uniformData)
{ {
uint32 shaderAluConst; uint32 shaderAluConst;
@ -92,7 +90,7 @@ void LatteBufferCache_LoadRemappedUniforms(LatteDecompilerShader* shader, float*
shaderUniformRegisterOffset = mmSQ_GS_UNIFORM_BLOCK_START; shaderUniformRegisterOffset = mmSQ_GS_UNIFORM_BLOCK_START;
break; break;
default: default:
cemu_assert_debug(false); UNREACHABLE;
} }
// sourced from uniform registers // sourced from uniform registers
@ -110,11 +108,11 @@ void LatteBufferCache_LoadRemappedUniforms(LatteDecompilerShader* shader, float*
MPTR physicalAddr = LatteGPUState.contextRegister[shaderUniformRegisterOffset + bufferGroup.kcacheBankIdOffset / 4]; MPTR physicalAddr = LatteGPUState.contextRegister[shaderUniformRegisterOffset + bufferGroup.kcacheBankIdOffset / 4];
if (physicalAddr) if (physicalAddr)
{ {
uint8* uniformBase = memory_base + physicalAddr; uint8* __restrict uniformBase = memory_base + physicalAddr;
for (auto& it : bufferGroup.entries) for (auto& it : bufferGroup.entries)
{ {
uint64* regDest = (uint64*)((uint8*)uniformData + it.mappedIndexOffset); uint64* __restrict regDest = (uint64*)((uint8*)uniformData + it.mappedIndexOffset);
uint64* uniformEntrySrc = (uint64*)(uniformBase + it.indexOffset); uint64* __restrict uniformEntrySrc = (uint64*)(uniformBase + it.indexOffset);
memcpy(regDest, uniformEntrySrc, 16); memcpy(regDest, uniformEntrySrc, 16);
} }
} }

View File

@ -3791,6 +3791,7 @@ void VulkanRenderer::bufferCache_init(const sint32 bufferSize)
m_importedMemBaseAddress = 0x10000000; m_importedMemBaseAddress = 0x10000000;
size_t hostAllocationSize = 0x40000000ull; size_t hostAllocationSize = 0x40000000ull;
// todo - get size of allocation // todo - get size of allocation
/*
bool configUseHostMemory = false; // todo - replace this with a config option bool configUseHostMemory = false; // todo - replace this with a config option
m_useHostMemoryForCache = false; m_useHostMemoryForCache = false;
if (m_featureControl.deviceExtensions.external_memory_host && configUseHostMemory) if (m_featureControl.deviceExtensions.external_memory_host && configUseHostMemory)
@ -3801,6 +3802,7 @@ void VulkanRenderer::bufferCache_init(const sint32 bufferSize)
cemuLog_log(LogType::Force, "Unable to import host memory to Vulkan buffer. Use default cache system instead"); cemuLog_log(LogType::Force, "Unable to import host memory to Vulkan buffer. Use default cache system instead");
} }
} }
*/
if(!m_useHostMemoryForCache) if(!m_useHostMemoryForCache)
memoryManager->CreateBuffer(bufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT, 0, m_bufferCache, m_bufferCacheMemory); memoryManager->CreateBuffer(bufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT, 0, m_bufferCache, m_bufferCacheMemory);
} }

View File

@ -635,7 +635,7 @@ private:
// if VK_EXT_external_memory_host is supported we can (optionally) import all of the Wii U memory into a Vulkan memory object // if VK_EXT_external_memory_host is supported we can (optionally) import all of the Wii U memory into a Vulkan memory object
// this allows us to skip any vertex/uniform caching logic and let the GPU directly read the memory from main RAM // this allows us to skip any vertex/uniform caching logic and let the GPU directly read the memory from main RAM
// Wii U memory imported into a buffer // Wii U memory imported into a buffer
bool m_useHostMemoryForCache{ false }; static constexpr bool m_useHostMemoryForCache{ false }; // currently disabled and made constexpr so the compiler eliminates the branches that will never be taken
VkBuffer m_importedMem = VK_NULL_HANDLE; VkBuffer m_importedMem = VK_NULL_HANDLE;
VkDeviceMemory m_importedMemMemory = VK_NULL_HANDLE; VkDeviceMemory m_importedMemMemory = VK_NULL_HANDLE;
MPTR m_importedMemBaseAddress = 0; MPTR m_importedMemBaseAddress = 0;

View File

@ -456,9 +456,7 @@ void VulkanRenderer::uniformData_updateUniformVars(uint32 shaderStageIndex, Latt
} }
} }
void VulkanRenderer::draw_prepareDynamicOffsetsForDescriptorSet(uint32 shaderStageIndex, uint32* dynamicOffsets, void VulkanRenderer::draw_prepareDynamicOffsetsForDescriptorSet(uint32 shaderStageIndex, uint32* dynamicOffsets, sint32& numDynOffsets, const PipelineInfo* pipeline_info)
sint32& numDynOffsets,
const PipelineInfo* pipeline_info)
{ {
numDynOffsets = 0; numDynOffsets = 0;
if (pipeline_info->dynamicOffsetInfo.hasUniformVar[shaderStageIndex]) if (pipeline_info->dynamicOffsetInfo.hasUniformVar[shaderStageIndex])
@ -1355,7 +1353,6 @@ void VulkanRenderer::draw_execute(uint32 baseVertex, uint32 baseInstance, uint32
LatteIndices_decode(memory_getPointerFromVirtualOffset(indexDataMPTR), indexType, count, primitiveMode, indexMin, indexMax, hostIndexType, hostIndexCount, indexAllocation); LatteIndices_decode(memory_getPointerFromVirtualOffset(indexDataMPTR), indexType, count, primitiveMode, indexMin, indexMax, hostIndexType, hostIndexCount, indexAllocation);
VKRSynchronizedHeapAllocator::AllocatorReservation* indexReservation = (VKRSynchronizedHeapAllocator::AllocatorReservation*)indexAllocation.rendererInternal; VKRSynchronizedHeapAllocator::AllocatorReservation* indexReservation = (VKRSynchronizedHeapAllocator::AllocatorReservation*)indexAllocation.rendererInternal;
// update index binding // update index binding
bool isPrevIndexData = false;
if (hostIndexType != INDEX_TYPE::NONE) if (hostIndexType != INDEX_TYPE::NONE)
{ {
uint32 indexBufferIndex = indexReservation->bufferIndex; uint32 indexBufferIndex = indexReservation->bufferIndex;
@ -1374,8 +1371,6 @@ void VulkanRenderer::draw_execute(uint32 baseVertex, uint32 baseInstance, uint32
cemu_assert(false); cemu_assert(false);
vkCmdBindIndexBuffer(m_state.currentCommandBuffer, indexReservation->vkBuffer, indexBufferOffset, vkType); vkCmdBindIndexBuffer(m_state.currentCommandBuffer, indexReservation->vkBuffer, indexBufferOffset, vkType);
} }
else
isPrevIndexData = true;
} }
if (m_useHostMemoryForCache) if (m_useHostMemoryForCache)
@ -1480,45 +1475,32 @@ void VulkanRenderer::draw_execute(uint32 baseVertex, uint32 baseInstance, uint32
// update vertex and pixel descriptor set in a single call to vkCmdBindDescriptorSets // update vertex and pixel descriptor set in a single call to vkCmdBindDescriptorSets
sint32 numDynOffsetsVS; sint32 numDynOffsetsVS;
sint32 numDynOffsetsPS; sint32 numDynOffsetsPS;
draw_prepareDynamicOffsetsForDescriptorSet(VulkanRendererConst::SHADER_STAGE_INDEX_VERTEX, dynamicOffsets, numDynOffsetsVS, draw_prepareDynamicOffsetsForDescriptorSet(VulkanRendererConst::SHADER_STAGE_INDEX_VERTEX, dynamicOffsets, numDynOffsetsVS, pipeline_info);
pipeline_info); draw_prepareDynamicOffsetsForDescriptorSet(VulkanRendererConst::SHADER_STAGE_INDEX_FRAGMENT, dynamicOffsets + numDynOffsetsVS, numDynOffsetsPS, pipeline_info);
draw_prepareDynamicOffsetsForDescriptorSet(VulkanRendererConst::SHADER_STAGE_INDEX_FRAGMENT, dynamicOffsets + numDynOffsetsVS, numDynOffsetsPS,
pipeline_info);
VkDescriptorSet dsArray[2]; VkDescriptorSet dsArray[2];
dsArray[0] = vertexDS->m_vkObjDescriptorSet->descriptorSet; dsArray[0] = vertexDS->m_vkObjDescriptorSet->descriptorSet;
dsArray[1] = pixelDS->m_vkObjDescriptorSet->descriptorSet; dsArray[1] = pixelDS->m_vkObjDescriptorSet->descriptorSet;
vkCmdBindDescriptorSets(m_state.currentCommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, vkCmdBindDescriptorSets(m_state.currentCommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, vkObjPipeline->m_pipelineLayout, 0, 2, dsArray, numDynOffsetsVS + numDynOffsetsPS, dynamicOffsets);
vkObjPipeline->m_pipelineLayout, 0, 2, dsArray, numDynOffsetsVS + numDynOffsetsPS,
dynamicOffsets);
} }
else if (vertexDS) else if (vertexDS)
{ {
sint32 numDynOffsets; sint32 numDynOffsets;
draw_prepareDynamicOffsetsForDescriptorSet(VulkanRendererConst::SHADER_STAGE_INDEX_VERTEX, dynamicOffsets, numDynOffsets, draw_prepareDynamicOffsetsForDescriptorSet(VulkanRendererConst::SHADER_STAGE_INDEX_VERTEX, dynamicOffsets, numDynOffsets, pipeline_info);
pipeline_info); vkCmdBindDescriptorSets(m_state.currentCommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, vkObjPipeline->m_pipelineLayout, 0, 1, &vertexDS->m_vkObjDescriptorSet->descriptorSet, numDynOffsets, dynamicOffsets);
vkCmdBindDescriptorSets(m_state.currentCommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
vkObjPipeline->m_pipelineLayout, 0, 1, &vertexDS->m_vkObjDescriptorSet->descriptorSet, numDynOffsets,
dynamicOffsets);
} }
else if (pixelDS) else if (pixelDS)
{ {
sint32 numDynOffsets; sint32 numDynOffsets;
draw_prepareDynamicOffsetsForDescriptorSet(VulkanRendererConst::SHADER_STAGE_INDEX_FRAGMENT, dynamicOffsets, numDynOffsets, draw_prepareDynamicOffsetsForDescriptorSet(VulkanRendererConst::SHADER_STAGE_INDEX_FRAGMENT, dynamicOffsets, numDynOffsets, pipeline_info);
pipeline_info); vkCmdBindDescriptorSets(m_state.currentCommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, vkObjPipeline->m_pipelineLayout, 1, 1, &pixelDS->m_vkObjDescriptorSet->descriptorSet, numDynOffsets, dynamicOffsets);
vkCmdBindDescriptorSets(m_state.currentCommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
vkObjPipeline->m_pipelineLayout, 1, 1, &pixelDS->m_vkObjDescriptorSet->descriptorSet, numDynOffsets,
dynamicOffsets);
} }
if (geometryDS) if (geometryDS)
{ {
sint32 numDynOffsets; sint32 numDynOffsets;
draw_prepareDynamicOffsetsForDescriptorSet(VulkanRendererConst::SHADER_STAGE_INDEX_GEOMETRY, dynamicOffsets, numDynOffsets, draw_prepareDynamicOffsetsForDescriptorSet(VulkanRendererConst::SHADER_STAGE_INDEX_GEOMETRY, dynamicOffsets, numDynOffsets, pipeline_info);
pipeline_info); vkCmdBindDescriptorSets(m_state.currentCommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, vkObjPipeline->m_pipelineLayout, 2, 1, &geometryDS->m_vkObjDescriptorSet->descriptorSet, numDynOffsets, dynamicOffsets);
vkCmdBindDescriptorSets(m_state.currentCommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
vkObjPipeline->m_pipelineLayout, 2, 1, &geometryDS->m_vkObjDescriptorSet->descriptorSet, numDynOffsets,
dynamicOffsets);
} }
// draw // draw