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

View File

@ -3791,6 +3791,7 @@ void VulkanRenderer::bufferCache_init(const sint32 bufferSize)
m_importedMemBaseAddress = 0x10000000;
size_t hostAllocationSize = 0x40000000ull;
// todo - get size of allocation
/*
bool configUseHostMemory = false; // todo - replace this with a config option
m_useHostMemoryForCache = false;
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");
}
}
*/
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);
}

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
// 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
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;
VkDeviceMemory m_importedMemMemory = VK_NULL_HANDLE;
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,
sint32& numDynOffsets,
const PipelineInfo* pipeline_info)
void VulkanRenderer::draw_prepareDynamicOffsetsForDescriptorSet(uint32 shaderStageIndex, uint32* dynamicOffsets, sint32& numDynOffsets, const PipelineInfo* pipeline_info)
{
numDynOffsets = 0;
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);
VKRSynchronizedHeapAllocator::AllocatorReservation* indexReservation = (VKRSynchronizedHeapAllocator::AllocatorReservation*)indexAllocation.rendererInternal;
// update index binding
bool isPrevIndexData = false;
if (hostIndexType != INDEX_TYPE::NONE)
{
uint32 indexBufferIndex = indexReservation->bufferIndex;
@ -1374,8 +1371,6 @@ void VulkanRenderer::draw_execute(uint32 baseVertex, uint32 baseInstance, uint32
cemu_assert(false);
vkCmdBindIndexBuffer(m_state.currentCommandBuffer, indexReservation->vkBuffer, indexBufferOffset, vkType);
}
else
isPrevIndexData = true;
}
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
sint32 numDynOffsetsVS;
sint32 numDynOffsetsPS;
draw_prepareDynamicOffsetsForDescriptorSet(VulkanRendererConst::SHADER_STAGE_INDEX_VERTEX, dynamicOffsets, numDynOffsetsVS,
pipeline_info);
draw_prepareDynamicOffsetsForDescriptorSet(VulkanRendererConst::SHADER_STAGE_INDEX_FRAGMENT, dynamicOffsets + numDynOffsetsVS, numDynOffsetsPS,
pipeline_info);
draw_prepareDynamicOffsetsForDescriptorSet(VulkanRendererConst::SHADER_STAGE_INDEX_VERTEX, dynamicOffsets, numDynOffsetsVS, pipeline_info);
draw_prepareDynamicOffsetsForDescriptorSet(VulkanRendererConst::SHADER_STAGE_INDEX_FRAGMENT, dynamicOffsets + numDynOffsetsVS, numDynOffsetsPS, pipeline_info);
VkDescriptorSet dsArray[2];
dsArray[0] = vertexDS->m_vkObjDescriptorSet->descriptorSet;
dsArray[1] = pixelDS->m_vkObjDescriptorSet->descriptorSet;
vkCmdBindDescriptorSets(m_state.currentCommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
vkObjPipeline->m_pipelineLayout, 0, 2, dsArray, numDynOffsetsVS + numDynOffsetsPS,
dynamicOffsets);
vkCmdBindDescriptorSets(m_state.currentCommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, vkObjPipeline->m_pipelineLayout, 0, 2, dsArray, numDynOffsetsVS + numDynOffsetsPS, dynamicOffsets);
}
else if (vertexDS)
{
sint32 numDynOffsets;
draw_prepareDynamicOffsetsForDescriptorSet(VulkanRendererConst::SHADER_STAGE_INDEX_VERTEX, dynamicOffsets, numDynOffsets,
pipeline_info);
vkCmdBindDescriptorSets(m_state.currentCommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
vkObjPipeline->m_pipelineLayout, 0, 1, &vertexDS->m_vkObjDescriptorSet->descriptorSet, numDynOffsets,
dynamicOffsets);
draw_prepareDynamicOffsetsForDescriptorSet(VulkanRendererConst::SHADER_STAGE_INDEX_VERTEX, dynamicOffsets, numDynOffsets, pipeline_info);
vkCmdBindDescriptorSets(m_state.currentCommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, vkObjPipeline->m_pipelineLayout, 0, 1, &vertexDS->m_vkObjDescriptorSet->descriptorSet, numDynOffsets, dynamicOffsets);
}
else if (pixelDS)
{
sint32 numDynOffsets;
draw_prepareDynamicOffsetsForDescriptorSet(VulkanRendererConst::SHADER_STAGE_INDEX_FRAGMENT, dynamicOffsets, numDynOffsets,
pipeline_info);
vkCmdBindDescriptorSets(m_state.currentCommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
vkObjPipeline->m_pipelineLayout, 1, 1, &pixelDS->m_vkObjDescriptorSet->descriptorSet, numDynOffsets,
dynamicOffsets);
draw_prepareDynamicOffsetsForDescriptorSet(VulkanRendererConst::SHADER_STAGE_INDEX_FRAGMENT, dynamicOffsets, numDynOffsets, pipeline_info);
vkCmdBindDescriptorSets(m_state.currentCommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, vkObjPipeline->m_pipelineLayout, 1, 1, &pixelDS->m_vkObjDescriptorSet->descriptorSet, numDynOffsets, dynamicOffsets);
}
if (geometryDS)
{
sint32 numDynOffsets;
draw_prepareDynamicOffsetsForDescriptorSet(VulkanRendererConst::SHADER_STAGE_INDEX_GEOMETRY, dynamicOffsets, numDynOffsets,
pipeline_info);
vkCmdBindDescriptorSets(m_state.currentCommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
vkObjPipeline->m_pipelineLayout, 2, 1, &geometryDS->m_vkObjDescriptorSet->descriptorSet, numDynOffsets,
dynamicOffsets);
draw_prepareDynamicOffsetsForDescriptorSet(VulkanRendererConst::SHADER_STAGE_INDEX_GEOMETRY, dynamicOffsets, numDynOffsets, pipeline_info);
vkCmdBindDescriptorSets(m_state.currentCommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, vkObjPipeline->m_pipelineLayout, 2, 1, &geometryDS->m_vkObjDescriptorSet->descriptorSet, numDynOffsets, dynamicOffsets);
}
// draw