Vulkan: Fix a validation error + minor code refactor

We were using VK_EXT_DEPTH_CLIP_ENABLE but didn't actually request it.

Also fixed an assert when closing Cemu caused by incorrectly tracking the number of allocated pipelines
This commit is contained in:
Exzap 2025-04-15 21:10:11 +02:00
parent c4eab08f30
commit cd6eb1097b
8 changed files with 73 additions and 63 deletions

View file

@ -221,11 +221,14 @@ public:
VKRObjectPipeline(); VKRObjectPipeline();
~VKRObjectPipeline() override; ~VKRObjectPipeline() override;
void setPipeline(VkPipeline newPipeline); void SetPipeline(VkPipeline newPipeline);
VkPipeline GetPipeline() const { return m_pipeline; }
VkPipeline pipeline = VK_NULL_HANDLE; VkDescriptorSetLayout m_vertexDSL = VK_NULL_HANDLE, m_pixelDSL = VK_NULL_HANDLE, m_geometryDSL = VK_NULL_HANDLE;
VkDescriptorSetLayout vertexDSL = VK_NULL_HANDLE, pixelDSL = VK_NULL_HANDLE, geometryDSL = VK_NULL_HANDLE; VkPipelineLayout m_pipelineLayout = VK_NULL_HANDLE;
VkPipelineLayout pipeline_layout = VK_NULL_HANDLE;
private:
VkPipeline m_pipeline = VK_NULL_HANDLE;
}; };
class VKRObjectDescriptorSet : public VKRDestructibleObject class VKRObjectDescriptorSet : public VKRDestructibleObject

View file

@ -26,7 +26,6 @@ PipelineInfo::PipelineInfo(uint64 minimalStateHash, uint64 pipelineHash, LatteFe
// init VKRObjPipeline // init VKRObjPipeline
m_vkrObjPipeline = new VKRObjectPipeline(); m_vkrObjPipeline = new VKRObjectPipeline();
m_vkrObjPipeline->pipeline = VK_NULL_HANDLE;
// track dependency with shaders // track dependency with shaders
if (vertexShaderVk) if (vertexShaderVk)

View file

@ -558,8 +558,8 @@ void PipelineCompiler::InitRasterizerState(const LatteContextRegister& latteRegi
rasterizerExt.flags = 0; rasterizerExt.flags = 0;
rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
rasterizer.pNext = &rasterizerExt;
rasterizer.rasterizerDiscardEnable = LatteGPUState.contextNew.PA_CL_CLIP_CNTL.get_DX_RASTERIZATION_KILL(); rasterizer.rasterizerDiscardEnable = LatteGPUState.contextNew.PA_CL_CLIP_CNTL.get_DX_RASTERIZATION_KILL();
rasterizer.pNext = VulkanRenderer::GetInstance()->m_featureControl.deviceExtensions.depth_clip_enable ? &rasterizerExt : nullptr;
// GX2SetSpecialState(0, true) workaround // GX2SetSpecialState(0, true) workaround
if (!LatteGPUState.contextNew.PA_CL_VTE_CNTL.get_VPORT_X_OFFSET_ENA()) if (!LatteGPUState.contextNew.PA_CL_VTE_CNTL.get_VPORT_X_OFFSET_ENA())
rasterizer.rasterizerDiscardEnable = false; rasterizer.rasterizerDiscardEnable = false;
@ -730,7 +730,7 @@ void PipelineCompiler::InitDescriptorSetLayouts(VulkanRenderer* vkRenderer, Pipe
{ {
cemu_assert_debug(descriptorSetLayoutCount == 0); cemu_assert_debug(descriptorSetLayoutCount == 0);
CreateDescriptorSetLayout(vkRenderer, vertexShader, descriptorSetLayout[descriptorSetLayoutCount], vkrPipelineInfo); CreateDescriptorSetLayout(vkRenderer, vertexShader, descriptorSetLayout[descriptorSetLayoutCount], vkrPipelineInfo);
vkObjPipeline->vertexDSL = descriptorSetLayout[descriptorSetLayoutCount]; vkObjPipeline->m_vertexDSL = descriptorSetLayout[descriptorSetLayoutCount];
descriptorSetLayoutCount++; descriptorSetLayoutCount++;
} }
@ -738,7 +738,7 @@ void PipelineCompiler::InitDescriptorSetLayouts(VulkanRenderer* vkRenderer, Pipe
{ {
cemu_assert_debug(descriptorSetLayoutCount == 1); cemu_assert_debug(descriptorSetLayoutCount == 1);
CreateDescriptorSetLayout(vkRenderer, pixelShader, descriptorSetLayout[descriptorSetLayoutCount], vkrPipelineInfo); CreateDescriptorSetLayout(vkRenderer, pixelShader, descriptorSetLayout[descriptorSetLayoutCount], vkrPipelineInfo);
vkObjPipeline->pixelDSL = descriptorSetLayout[descriptorSetLayoutCount]; vkObjPipeline->m_pixelDSL = descriptorSetLayout[descriptorSetLayoutCount];
descriptorSetLayoutCount++; descriptorSetLayoutCount++;
} }
else if (geometryShader) else if (geometryShader)
@ -757,7 +757,7 @@ void PipelineCompiler::InitDescriptorSetLayouts(VulkanRenderer* vkRenderer, Pipe
{ {
cemu_assert_debug(descriptorSetLayoutCount == 2); cemu_assert_debug(descriptorSetLayoutCount == 2);
CreateDescriptorSetLayout(vkRenderer, geometryShader, descriptorSetLayout[descriptorSetLayoutCount], vkrPipelineInfo); CreateDescriptorSetLayout(vkRenderer, geometryShader, descriptorSetLayout[descriptorSetLayoutCount], vkrPipelineInfo);
vkObjPipeline->geometryDSL = descriptorSetLayout[descriptorSetLayoutCount]; vkObjPipeline->m_geometryDSL = descriptorSetLayout[descriptorSetLayoutCount];
descriptorSetLayoutCount++; descriptorSetLayoutCount++;
} }
} }
@ -918,7 +918,7 @@ bool PipelineCompiler::InitFromCurrentGPUState(PipelineInfo* pipelineInfo, const
pipelineLayoutInfo.pPushConstantRanges = nullptr; pipelineLayoutInfo.pPushConstantRanges = nullptr;
pipelineLayoutInfo.pushConstantRangeCount = 0; pipelineLayoutInfo.pushConstantRangeCount = 0;
VkResult result = vkCreatePipelineLayout(vkRenderer->m_logicalDevice, &pipelineLayoutInfo, nullptr, &m_pipeline_layout); VkResult result = vkCreatePipelineLayout(vkRenderer->m_logicalDevice, &pipelineLayoutInfo, nullptr, &m_pipelineLayout);
if (result != VK_SUCCESS) if (result != VK_SUCCESS)
{ {
cemuLog_log(LogType::Force, "Failed to create pipeline layout: {}", result); cemuLog_log(LogType::Force, "Failed to create pipeline layout: {}", result);
@ -936,7 +936,7 @@ bool PipelineCompiler::InitFromCurrentGPUState(PipelineInfo* pipelineInfo, const
// ########################################################################################################################################## // ##########################################################################################################################################
pipelineInfo->m_vkrObjPipeline->pipeline_layout = m_pipeline_layout; pipelineInfo->m_vkrObjPipeline->m_pipelineLayout = m_pipelineLayout;
// increment ref counter for vkrObjPipeline and renderpass object to make sure they dont get released while we are using them // increment ref counter for vkrObjPipeline and renderpass object to make sure they dont get released while we are using them
m_vkrObjPipeline->incRef(); m_vkrObjPipeline->incRef();
@ -989,7 +989,7 @@ bool PipelineCompiler::Compile(bool forceCompile, bool isRenderThread, bool show
pipelineInfo.pRasterizationState = &rasterizer; pipelineInfo.pRasterizationState = &rasterizer;
pipelineInfo.pMultisampleState = &multisampling; pipelineInfo.pMultisampleState = &multisampling;
pipelineInfo.pColorBlendState = &colorBlending; pipelineInfo.pColorBlendState = &colorBlending;
pipelineInfo.layout = m_pipeline_layout; pipelineInfo.layout = m_pipelineLayout;
pipelineInfo.renderPass = m_renderPassObj->m_renderPass; pipelineInfo.renderPass = m_renderPassObj->m_renderPass;
pipelineInfo.pDepthStencilState = &depthStencilState; pipelineInfo.pDepthStencilState = &depthStencilState;
pipelineInfo.subpass = 0; pipelineInfo.subpass = 0;
@ -1037,7 +1037,7 @@ bool PipelineCompiler::Compile(bool forceCompile, bool isRenderThread, bool show
} }
else if (result == VK_SUCCESS) else if (result == VK_SUCCESS)
{ {
m_vkrObjPipeline->setPipeline(pipeline); m_vkrObjPipeline->SetPipeline(pipeline);
} }
else else
{ {

View file

@ -41,7 +41,7 @@ public:
bool InitFromCurrentGPUState(PipelineInfo* pipelineInfo, const LatteContextRegister& latteRegister, VKRObjectRenderPass* renderPassObj); bool InitFromCurrentGPUState(PipelineInfo* pipelineInfo, const LatteContextRegister& latteRegister, VKRObjectRenderPass* renderPassObj);
void TrackAsCached(uint64 baseHash, uint64 pipelineStateHash); // stores pipeline to permanent cache if not yet cached. Must be called synchronously from render thread due to dependency on GPU state void TrackAsCached(uint64 baseHash, uint64 pipelineStateHash); // stores pipeline to permanent cache if not yet cached. Must be called synchronously from render thread due to dependency on GPU state
VkPipelineLayout m_pipeline_layout; VkPipelineLayout m_pipelineLayout;
VKRObjectRenderPass* m_renderPassObj{}; VKRObjectRenderPass* m_renderPassObj{};
/* shader stages */ /* shader stages */

View file

@ -49,7 +49,8 @@ const std::vector<const char*> kOptionalDeviceExtensions =
VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME, VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME,
VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME, VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME,
VK_KHR_PRESENT_WAIT_EXTENSION_NAME, VK_KHR_PRESENT_WAIT_EXTENSION_NAME,
VK_KHR_PRESENT_ID_EXTENSION_NAME VK_KHR_PRESENT_ID_EXTENSION_NAME,
VK_EXT_DEPTH_CLIP_ENABLE_EXTENSION_NAME
}; };
const std::vector<const char*> kRequiredDeviceExtensions = const std::vector<const char*> kRequiredDeviceExtensions =
@ -82,8 +83,6 @@ VKAPI_ATTR VkBool32 VKAPI_CALL DebugUtilsCallback(VkDebugUtilsMessageSeverityFla
if (strstr(pCallbackData->pMessage, "Number of currently valid sampler objects is not less than the maximum allowed")) if (strstr(pCallbackData->pMessage, "Number of currently valid sampler objects is not less than the maximum allowed"))
return VK_FALSE; return VK_FALSE;
assert_dbg();
#endif #endif
cemuLog_log(LogType::Force, (char*)pCallbackData->pMessage); cemuLog_log(LogType::Force, (char*)pCallbackData->pMessage);
@ -314,7 +313,10 @@ void VulkanRenderer::GetDeviceFeatures()
cemuLog_log(LogType::Force, "VK_EXT_custom_border_color not supported. Cannot emulate arbitrary border color"); cemuLog_log(LogType::Force, "VK_EXT_custom_border_color not supported. Cannot emulate arbitrary border color");
} }
} }
if (!m_featureControl.deviceExtensions.depth_clip_enable)
{
cemuLog_log(LogType::Force, "VK_EXT_depth_clip_enable not supported");
}
// get limits // get limits
m_featureControl.limits.minUniformBufferOffsetAlignment = std::max(prop2.properties.limits.minUniformBufferOffsetAlignment, (VkDeviceSize)4); m_featureControl.limits.minUniformBufferOffsetAlignment = std::max(prop2.properties.limits.minUniformBufferOffsetAlignment, (VkDeviceSize)4);
m_featureControl.limits.nonCoherentAtomSize = std::max(prop2.properties.limits.nonCoherentAtomSize, (VkDeviceSize)4); m_featureControl.limits.nonCoherentAtomSize = std::max(prop2.properties.limits.nonCoherentAtomSize, (VkDeviceSize)4);
@ -1118,10 +1120,13 @@ VkDeviceCreateInfo VulkanRenderer::CreateDeviceCreateInfo(const std::vector<VkDe
used_extensions.emplace_back(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME); used_extensions.emplace_back(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME);
if (m_featureControl.deviceExtensions.shader_float_controls) if (m_featureControl.deviceExtensions.shader_float_controls)
used_extensions.emplace_back(VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME); used_extensions.emplace_back(VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME);
if (m_featureControl.deviceExtensions.depth_clip_enable)
used_extensions.emplace_back(VK_EXT_DEPTH_CLIP_ENABLE_EXTENSION_NAME);
if (m_featureControl.deviceExtensions.present_wait) if (m_featureControl.deviceExtensions.present_wait)
{
used_extensions.emplace_back(VK_KHR_PRESENT_ID_EXTENSION_NAME); used_extensions.emplace_back(VK_KHR_PRESENT_ID_EXTENSION_NAME);
if (m_featureControl.deviceExtensions.present_wait)
used_extensions.emplace_back(VK_KHR_PRESENT_WAIT_EXTENSION_NAME); used_extensions.emplace_back(VK_KHR_PRESENT_WAIT_EXTENSION_NAME);
}
VkDeviceCreateInfo createInfo{}; VkDeviceCreateInfo createInfo{};
createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
@ -1218,6 +1223,7 @@ bool VulkanRenderer::CheckDeviceExtensionSupport(const VkPhysicalDevice device,
info.deviceExtensions.synchronization2 = isExtensionAvailable(VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME); info.deviceExtensions.synchronization2 = isExtensionAvailable(VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME);
info.deviceExtensions.shader_float_controls = isExtensionAvailable(VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME); info.deviceExtensions.shader_float_controls = isExtensionAvailable(VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME);
info.deviceExtensions.dynamic_rendering = false; // isExtensionAvailable(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME); info.deviceExtensions.dynamic_rendering = false; // isExtensionAvailable(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME);
info.deviceExtensions.depth_clip_enable = isExtensionAvailable(VK_EXT_DEPTH_CLIP_ENABLE_EXTENSION_NAME);
// dynamic rendering doesn't provide any benefits for us right now. Driver implementations are very unoptimized as of Feb 2022 // dynamic rendering doesn't provide any benefits for us right now. Driver implementations are very unoptimized as of Feb 2022
info.deviceExtensions.present_wait = isExtensionAvailable(VK_KHR_PRESENT_WAIT_EXTENSION_NAME) && isExtensionAvailable(VK_KHR_PRESENT_ID_EXTENSION_NAME); info.deviceExtensions.present_wait = isExtensionAvailable(VK_KHR_PRESENT_WAIT_EXTENSION_NAME) && isExtensionAvailable(VK_KHR_PRESENT_ID_EXTENSION_NAME);
@ -4112,33 +4118,36 @@ VKRObjectFramebuffer::~VKRObjectFramebuffer()
VKRObjectPipeline::VKRObjectPipeline() VKRObjectPipeline::VKRObjectPipeline()
{ {
// todo
} }
void VKRObjectPipeline::setPipeline(VkPipeline newPipeline) void VKRObjectPipeline::SetPipeline(VkPipeline newPipeline)
{ {
cemu_assert_debug(pipeline == VK_NULL_HANDLE); if (m_pipeline == newPipeline)
pipeline = newPipeline; return;
if(newPipeline != VK_NULL_HANDLE) cemu_assert_debug(m_pipeline == VK_NULL_HANDLE); // replacing an already assigned pipeline is not intended
if(m_pipeline == VK_NULL_HANDLE && newPipeline != VK_NULL_HANDLE)
performanceMonitor.vk.numGraphicPipelines.increment(); performanceMonitor.vk.numGraphicPipelines.increment();
else if(m_pipeline != VK_NULL_HANDLE && newPipeline == VK_NULL_HANDLE)
performanceMonitor.vk.numGraphicPipelines.decrement();
m_pipeline = newPipeline;
} }
VKRObjectPipeline::~VKRObjectPipeline() VKRObjectPipeline::~VKRObjectPipeline()
{ {
auto vkr = VulkanRenderer::GetInstance(); auto vkr = VulkanRenderer::GetInstance();
if (pipeline != VK_NULL_HANDLE) if (m_pipeline != VK_NULL_HANDLE)
{ {
vkDestroyPipeline(vkr->GetLogicalDevice(), pipeline, nullptr); vkDestroyPipeline(vkr->GetLogicalDevice(), m_pipeline, nullptr);
performanceMonitor.vk.numGraphicPipelines.decrement(); performanceMonitor.vk.numGraphicPipelines.decrement();
} }
if (vertexDSL != VK_NULL_HANDLE) if (m_vertexDSL != VK_NULL_HANDLE)
vkDestroyDescriptorSetLayout(vkr->GetLogicalDevice(), vertexDSL, nullptr); vkDestroyDescriptorSetLayout(vkr->GetLogicalDevice(), m_vertexDSL, nullptr);
if (pixelDSL != VK_NULL_HANDLE) if (m_pixelDSL != VK_NULL_HANDLE)
vkDestroyDescriptorSetLayout(vkr->GetLogicalDevice(), pixelDSL, nullptr); vkDestroyDescriptorSetLayout(vkr->GetLogicalDevice(), m_pixelDSL, nullptr);
if (geometryDSL != VK_NULL_HANDLE) if (m_geometryDSL != VK_NULL_HANDLE)
vkDestroyDescriptorSetLayout(vkr->GetLogicalDevice(), geometryDSL, nullptr); vkDestroyDescriptorSetLayout(vkr->GetLogicalDevice(), m_geometryDSL, nullptr);
if (pipeline_layout != VK_NULL_HANDLE) if (m_pipelineLayout != VK_NULL_HANDLE)
vkDestroyPipelineLayout(vkr->GetLogicalDevice(), pipeline_layout, nullptr); vkDestroyPipelineLayout(vkr->GetLogicalDevice(), m_pipelineLayout, nullptr);
} }
VKRObjectDescriptorSet::VKRObjectDescriptorSet() VKRObjectDescriptorSet::VKRObjectDescriptorSet()

View file

@ -452,6 +452,7 @@ private:
bool dynamic_rendering = false; // VK_KHR_dynamic_rendering bool dynamic_rendering = false; // VK_KHR_dynamic_rendering
bool shader_float_controls = false; // VK_KHR_shader_float_controls bool shader_float_controls = false; // VK_KHR_shader_float_controls
bool present_wait = false; // VK_KHR_present_wait bool present_wait = false; // VK_KHR_present_wait
bool depth_clip_enable = false; // VK_EXT_depth_clip_enable
}deviceExtensions; }deviceExtensions;
struct struct

View file

@ -603,7 +603,7 @@ VkDescriptorSetInfo* VulkanRenderer::draw_getOrCreateDescriptorSet(PipelineInfo*
const auto it = pipeline_info->vertex_ds_cache.find(stateHash); const auto it = pipeline_info->vertex_ds_cache.find(stateHash);
if (it != pipeline_info->vertex_ds_cache.cend()) if (it != pipeline_info->vertex_ds_cache.cend())
return it->second; return it->second;
descriptor_set_layout = pipeline_info->m_vkrObjPipeline->vertexDSL; descriptor_set_layout = pipeline_info->m_vkrObjPipeline->m_vertexDSL;
break; break;
} }
case LatteConst::ShaderType::Pixel: case LatteConst::ShaderType::Pixel:
@ -611,7 +611,7 @@ VkDescriptorSetInfo* VulkanRenderer::draw_getOrCreateDescriptorSet(PipelineInfo*
const auto it = pipeline_info->pixel_ds_cache.find(stateHash); const auto it = pipeline_info->pixel_ds_cache.find(stateHash);
if (it != pipeline_info->pixel_ds_cache.cend()) if (it != pipeline_info->pixel_ds_cache.cend())
return it->second; return it->second;
descriptor_set_layout = pipeline_info->m_vkrObjPipeline->pixelDSL; descriptor_set_layout = pipeline_info->m_vkrObjPipeline->m_pixelDSL;
break; break;
} }
case LatteConst::ShaderType::Geometry: case LatteConst::ShaderType::Geometry:
@ -619,7 +619,7 @@ VkDescriptorSetInfo* VulkanRenderer::draw_getOrCreateDescriptorSet(PipelineInfo*
const auto it = pipeline_info->geometry_ds_cache.find(stateHash); const auto it = pipeline_info->geometry_ds_cache.find(stateHash);
if (it != pipeline_info->geometry_ds_cache.cend()) if (it != pipeline_info->geometry_ds_cache.cend())
return it->second; return it->second;
descriptor_set_layout = pipeline_info->m_vkrObjPipeline->geometryDSL; descriptor_set_layout = pipeline_info->m_vkrObjPipeline->m_geometryDSL;
break; break;
} }
default: default:
@ -1481,8 +1481,7 @@ void VulkanRenderer::draw_execute(uint32 baseVertex, uint32 baseInstance, uint32
} }
auto vkObjPipeline = pipeline_info->m_vkrObjPipeline; auto vkObjPipeline = pipeline_info->m_vkrObjPipeline;
if (vkObjPipeline->GetPipeline() == VK_NULL_HANDLE)
if (vkObjPipeline->pipeline == VK_NULL_HANDLE)
{ {
// invalid/uninitialized pipeline // invalid/uninitialized pipeline
m_state.activeVertexDS = nullptr; m_state.activeVertexDS = nullptr;
@ -1509,11 +1508,11 @@ void VulkanRenderer::draw_execute(uint32 baseVertex, uint32 baseInstance, uint32
draw_setRenderPass(); draw_setRenderPass();
if (m_state.currentPipeline != vkObjPipeline->pipeline) if (m_state.currentPipeline != vkObjPipeline->GetPipeline())
{ {
vkCmdBindPipeline(m_state.currentCommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, vkObjPipeline->pipeline); vkCmdBindPipeline(m_state.currentCommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, vkObjPipeline->GetPipeline());
vkObjPipeline->flagForCurrentCommandBuffer(); vkObjPipeline->flagForCurrentCommandBuffer();
m_state.currentPipeline = vkObjPipeline->pipeline; m_state.currentPipeline = vkObjPipeline->GetPipeline();
// depth bias // depth bias
if (pipeline_info->usesDepthBias) if (pipeline_info->usesDepthBias)
draw_updateDepthBias(true); draw_updateDepthBias(true);
@ -1545,7 +1544,7 @@ void VulkanRenderer::draw_execute(uint32 baseVertex, uint32 baseInstance, uint32
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->pipeline_layout, 0, 2, dsArray, numDynOffsetsVS + numDynOffsetsPS, vkObjPipeline->m_pipelineLayout, 0, 2, dsArray, numDynOffsetsVS + numDynOffsetsPS,
dynamicOffsets); dynamicOffsets);
} }
else if (vertexDS) else if (vertexDS)
@ -1554,7 +1553,7 @@ void VulkanRenderer::draw_execute(uint32 baseVertex, uint32 baseInstance, uint32
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, vkCmdBindDescriptorSets(m_state.currentCommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
vkObjPipeline->pipeline_layout, 0, 1, &vertexDS->m_vkObjDescriptorSet->descriptorSet, numDynOffsets, vkObjPipeline->m_pipelineLayout, 0, 1, &vertexDS->m_vkObjDescriptorSet->descriptorSet, numDynOffsets,
dynamicOffsets); dynamicOffsets);
} }
else if (pixelDS) else if (pixelDS)
@ -1563,7 +1562,7 @@ void VulkanRenderer::draw_execute(uint32 baseVertex, uint32 baseInstance, uint32
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, vkCmdBindDescriptorSets(m_state.currentCommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
vkObjPipeline->pipeline_layout, 1, 1, &pixelDS->m_vkObjDescriptorSet->descriptorSet, numDynOffsets, vkObjPipeline->m_pipelineLayout, 1, 1, &pixelDS->m_vkObjDescriptorSet->descriptorSet, numDynOffsets,
dynamicOffsets); dynamicOffsets);
} }
if (geometryDS) if (geometryDS)
@ -1572,7 +1571,7 @@ void VulkanRenderer::draw_execute(uint32 baseVertex, uint32 baseInstance, uint32
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, vkCmdBindDescriptorSets(m_state.currentCommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
vkObjPipeline->pipeline_layout, 2, 1, &geometryDS->m_vkObjDescriptorSet->descriptorSet, numDynOffsets, vkObjPipeline->m_pipelineLayout, 2, 1, &geometryDS->m_vkObjDescriptorSet->descriptorSet, numDynOffsets,
dynamicOffsets); dynamicOffsets);
} }

View file

@ -357,7 +357,7 @@ CopySurfacePipelineInfo* VulkanRenderer::copySurface_getOrCreateGraphicsPipeline
layoutInfo.bindingCount = (uint32_t)descriptorSetLayoutBindings.size(); layoutInfo.bindingCount = (uint32_t)descriptorSetLayoutBindings.size();
layoutInfo.pBindings = descriptorSetLayoutBindings.data(); layoutInfo.pBindings = descriptorSetLayoutBindings.data();
if (vkCreateDescriptorSetLayout(m_logicalDevice, &layoutInfo, nullptr, &vkObjPipeline->pixelDSL) != VK_SUCCESS) if (vkCreateDescriptorSetLayout(m_logicalDevice, &layoutInfo, nullptr, &vkObjPipeline->m_pixelDSL) != VK_SUCCESS)
UnrecoverableError(fmt::format("Failed to create descriptor set layout for surface copy shader").c_str()); UnrecoverableError(fmt::format("Failed to create descriptor set layout for surface copy shader").c_str());
// ########################################################################################################################################## // ##########################################################################################################################################
@ -370,15 +370,15 @@ CopySurfacePipelineInfo* VulkanRenderer::copySurface_getOrCreateGraphicsPipeline
VkPipelineLayoutCreateInfo pipelineLayoutInfo{}; VkPipelineLayoutCreateInfo pipelineLayoutInfo{};
pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
pipelineLayoutInfo.setLayoutCount = 1; pipelineLayoutInfo.setLayoutCount = 1;
pipelineLayoutInfo.pSetLayouts = &vkObjPipeline->pixelDSL; pipelineLayoutInfo.pSetLayouts = &vkObjPipeline->m_pixelDSL;
pipelineLayoutInfo.pPushConstantRanges = &pushConstantRange; pipelineLayoutInfo.pPushConstantRanges = &pushConstantRange;
pipelineLayoutInfo.pushConstantRangeCount = 1; pipelineLayoutInfo.pushConstantRangeCount = 1;
VkResult result = vkCreatePipelineLayout(m_logicalDevice, &pipelineLayoutInfo, nullptr, &vkObjPipeline->pipeline_layout); VkResult result = vkCreatePipelineLayout(m_logicalDevice, &pipelineLayoutInfo, nullptr, &vkObjPipeline->m_pipelineLayout);
if (result != VK_SUCCESS) if (result != VK_SUCCESS)
{ {
cemuLog_log(LogType::Force, "Failed to create pipeline layout: {}", result); cemuLog_log(LogType::Force, "Failed to create pipeline layout: {}", result);
vkObjPipeline->pipeline = VK_NULL_HANDLE; vkObjPipeline->SetPipeline(VK_NULL_HANDLE);
return copyPipeline; return copyPipeline;
} }
@ -425,7 +425,7 @@ CopySurfacePipelineInfo* VulkanRenderer::copySurface_getOrCreateGraphicsPipeline
pipelineInfo.pRasterizationState = &rasterizer; pipelineInfo.pRasterizationState = &rasterizer;
pipelineInfo.pMultisampleState = &multisampling; pipelineInfo.pMultisampleState = &multisampling;
pipelineInfo.pColorBlendState = state.destinationTexture->isDepth?nullptr:&colorBlending; pipelineInfo.pColorBlendState = state.destinationTexture->isDepth?nullptr:&colorBlending;
pipelineInfo.layout = vkObjPipeline->pipeline_layout; pipelineInfo.layout = vkObjPipeline->m_pipelineLayout;
pipelineInfo.renderPass = copyPipeline->vkObjRenderPass->m_renderPass; pipelineInfo.renderPass = copyPipeline->vkObjRenderPass->m_renderPass;
pipelineInfo.pDepthStencilState = &depthStencilState; pipelineInfo.pDepthStencilState = &depthStencilState;
pipelineInfo.subpass = 0; pipelineInfo.subpass = 0;
@ -434,17 +434,16 @@ CopySurfacePipelineInfo* VulkanRenderer::copySurface_getOrCreateGraphicsPipeline
copyPipeline->vkObjPipeline = vkObjPipeline; copyPipeline->vkObjPipeline = vkObjPipeline;
result = vkCreateGraphicsPipelines(m_logicalDevice, m_pipeline_cache, 1, &pipelineInfo, nullptr, &copyPipeline->vkObjPipeline->pipeline); VkPipeline pipeline = VK_NULL_HANDLE;
result = vkCreateGraphicsPipelines(m_logicalDevice, m_pipeline_cache, 1, &pipelineInfo, nullptr, &pipeline);
if (result != VK_SUCCESS) if (result != VK_SUCCESS)
{ {
copyPipeline->vkObjPipeline->SetPipeline(nullptr);
cemuLog_log(LogType::Force, "Failed to create graphics pipeline for surface copy. Error {} Info:", (sint32)result); cemuLog_log(LogType::Force, "Failed to create graphics pipeline for surface copy. Error {} Info:", (sint32)result);
cemu_assert_debug(false); cemu_assert_suspicious();
copyPipeline->vkObjPipeline->pipeline = VK_NULL_HANDLE;
} }
//performanceMonitor.vk.numGraphicPipelines.increment(); else
copyPipeline->vkObjPipeline->SetPipeline(pipeline);
//m_pipeline_cache_semaphore.notify();
return copyPipeline; return copyPipeline;
} }
@ -522,7 +521,7 @@ VKRObjectDescriptorSet* VulkanRenderer::surfaceCopy_getOrCreateDescriptorSet(VkC
allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
allocInfo.descriptorPool = m_descriptorPool; allocInfo.descriptorPool = m_descriptorPool;
allocInfo.descriptorSetCount = 1; allocInfo.descriptorSetCount = 1;
allocInfo.pSetLayouts = &(pipelineInfo->vkObjPipeline->pixelDSL); allocInfo.pSetLayouts = &pipelineInfo->vkObjPipeline->m_pixelDSL;
if (vkAllocateDescriptorSets(m_logicalDevice, &allocInfo, &vkObjDescriptorSet->descriptorSet) != VK_SUCCESS) if (vkAllocateDescriptorSets(m_logicalDevice, &allocInfo, &vkObjDescriptorSet->descriptorSet) != VK_SUCCESS)
{ {
@ -644,7 +643,7 @@ void VulkanRenderer::surfaceCopy_viaDrawcall(LatteTextureVk* srcTextureVk, sint3
pushConstantData.srcTexelOffset[0] = 0; pushConstantData.srcTexelOffset[0] = 0;
pushConstantData.srcTexelOffset[1] = 0; pushConstantData.srcTexelOffset[1] = 0;
vkCmdPushConstants(m_state.currentCommandBuffer, copySurfacePipelineInfo->vkObjPipeline->pipeline_layout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(pushConstantData), &pushConstantData); vkCmdPushConstants(m_state.currentCommandBuffer, copySurfacePipelineInfo->vkObjPipeline->m_pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(pushConstantData), &pushConstantData);
// draw // draw
VkRenderPassBeginInfo renderPassInfo{}; VkRenderPassBeginInfo renderPassInfo{};
@ -680,13 +679,13 @@ void VulkanRenderer::surfaceCopy_viaDrawcall(LatteTextureVk* srcTextureVk, sint3
vkCmdBeginRenderPass(m_state.currentCommandBuffer, &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE); vkCmdBeginRenderPass(m_state.currentCommandBuffer, &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);
vkCmdBindPipeline(m_state.currentCommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, copySurfacePipelineInfo->vkObjPipeline->pipeline); vkCmdBindPipeline(m_state.currentCommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, copySurfacePipelineInfo->vkObjPipeline->GetPipeline());
copySurfacePipelineInfo->vkObjPipeline->flagForCurrentCommandBuffer(); copySurfacePipelineInfo->vkObjPipeline->flagForCurrentCommandBuffer();
m_state.currentPipeline = copySurfacePipelineInfo->vkObjPipeline->pipeline; m_state.currentPipeline = copySurfacePipelineInfo->vkObjPipeline->GetPipeline();
vkCmdBindDescriptorSets(m_state.currentCommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, vkCmdBindDescriptorSets(m_state.currentCommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
copySurfacePipelineInfo->vkObjPipeline->pipeline_layout, 0, 1, &vkObjDescriptorSet->descriptorSet, 0, nullptr); copySurfacePipelineInfo->vkObjPipeline->m_pipelineLayout, 0, 1, &vkObjDescriptorSet->descriptorSet, 0, nullptr);
vkObjDescriptorSet->flagForCurrentCommandBuffer(); vkObjDescriptorSet->flagForCurrentCommandBuffer();
vkCmdDraw(m_state.currentCommandBuffer, 6, 1, 0, 0); vkCmdDraw(m_state.currentCommandBuffer, 6, 1, 0, 0);