bool StateTracker::BindCompute() { if (!m_compute_shader) return false; // Can't kick compute in a render pass. if (InRenderPass()) EndRenderPass(); const VkCommandBuffer command_buffer = g_command_buffer_mgr->GetCurrentCommandBuffer(); if (m_dirty_flags & DIRTY_FLAG_COMPUTE_SHADER) { vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, m_compute_shader->GetComputePipeline()); } if (!UpdateComputeDescriptorSet()) { WARN_LOG(VIDEO, "Failed to get a compute descriptor set, executing buffer"); Renderer::GetInstance()->ExecuteCommandBuffer(false, false); if (!UpdateComputeDescriptorSet()) { // Something strange going on. ERROR_LOG(VIDEO, "Failed to get descriptor set, skipping dispatch"); return false; } } m_dirty_flags &= ~DIRTY_FLAG_COMPUTE_SHADER; return true; }
void StateTracker::SetFramebuffer(VkFramebuffer framebuffer, const VkRect2D& render_area) { // Should not be changed within a render pass. _assert_(!InRenderPass()); m_framebuffer = framebuffer; m_framebuffer_size = render_area; }
void StateTracker::EndRenderPass() { if (!InRenderPass()) return; vkCmdEndRenderPass(g_command_buffer_mgr->GetCurrentCommandBuffer()); m_current_render_pass = VK_NULL_HANDLE; }
bool StateTracker::Bind() { // Must have a pipeline. if (!m_pipeline) return false; // Check the render area if we were in a clear pass. if (m_current_render_pass == m_framebuffer->GetClearRenderPass() && !IsViewportWithinRenderArea()) EndRenderPass(); // Get a new descriptor set if any parts have changed if (!UpdateDescriptorSet()) { // We can fail to allocate descriptors if we exhaust the pool for this command buffer. WARN_LOG(VIDEO, "Failed to get a descriptor set, executing buffer"); Renderer::GetInstance()->ExecuteCommandBuffer(false, false); if (!UpdateDescriptorSet()) { // Something strange going on. ERROR_LOG(VIDEO, "Failed to get descriptor set, skipping draw"); return false; } } // Start render pass if not already started if (!InRenderPass()) BeginRenderPass(); // Re-bind parts of the pipeline const VkCommandBuffer command_buffer = g_command_buffer_mgr->GetCurrentCommandBuffer(); if (m_dirty_flags & DIRTY_FLAG_VERTEX_BUFFER) vkCmdBindVertexBuffers(command_buffer, 0, 1, &m_vertex_buffer, &m_vertex_buffer_offset); if (m_dirty_flags & DIRTY_FLAG_INDEX_BUFFER) vkCmdBindIndexBuffer(command_buffer, m_index_buffer, m_index_buffer_offset, m_index_type); if (m_dirty_flags & DIRTY_FLAG_PIPELINE) vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipeline->GetVkPipeline()); if (m_dirty_flags & DIRTY_FLAG_VIEWPORT) vkCmdSetViewport(command_buffer, 0, 1, &m_viewport); if (m_dirty_flags & DIRTY_FLAG_SCISSOR) vkCmdSetScissor(command_buffer, 0, 1, &m_scissor); m_dirty_flags &= ~(DIRTY_FLAG_VERTEX_BUFFER | DIRTY_FLAG_INDEX_BUFFER | DIRTY_FLAG_PIPELINE | DIRTY_FLAG_VIEWPORT | DIRTY_FLAG_SCISSOR); return true; }
void StateTracker::SetRenderPass(VkRenderPass load_render_pass, VkRenderPass clear_render_pass) { // Should not be changed within a render pass. _assert_(!InRenderPass()); // The clear and load render passes are compatible, so we don't need to change our pipeline. if (m_pipeline_state.render_pass != load_render_pass) { m_pipeline_state.render_pass = load_render_pass; m_dirty_flags |= DIRTY_FLAG_PIPELINE; } m_load_render_pass = load_render_pass; m_clear_render_pass = clear_render_pass; }
void StateTracker::BeginClearRenderPass(const VkRect2D& area, const VkClearValue* clear_values, u32 num_clear_values) { ASSERT(!InRenderPass()); m_current_render_pass = m_framebuffer->GetClearRenderPass(); m_framebuffer_render_area = area; VkRenderPassBeginInfo begin_info = {VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, nullptr, m_current_render_pass, m_framebuffer->GetFB(), m_framebuffer_render_area, num_clear_values, clear_values}; vkCmdBeginRenderPass(g_command_buffer_mgr->GetCurrentCommandBuffer(), &begin_info, VK_SUBPASS_CONTENTS_INLINE); }
void StateTracker::BeginDiscardRenderPass() { if (InRenderPass()) return; m_current_render_pass = m_framebuffer->GetDiscardRenderPass(); m_framebuffer_render_area = m_framebuffer->GetRect(); VkRenderPassBeginInfo begin_info = {VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, nullptr, m_current_render_pass, m_framebuffer->GetFB(), m_framebuffer_render_area, 0, nullptr}; vkCmdBeginRenderPass(g_command_buffer_mgr->GetCurrentCommandBuffer(), &begin_info, VK_SUBPASS_CONTENTS_INLINE); }
void StateTracker::SetFramebuffer(VKFramebuffer* framebuffer) { // Should not be changed within a render pass. ASSERT(!InRenderPass()); m_framebuffer = framebuffer; }
bool StateTracker::Bind(bool rebind_all /*= false*/) { // Check the render area if we were in a clear pass. if (m_current_render_pass == m_clear_render_pass && !IsViewportWithinRenderArea()) EndRenderPass(); // Get new pipeline object if any parts have changed if (m_dirty_flags & DIRTY_FLAG_PIPELINE && !UpdatePipeline()) { ERROR_LOG(VIDEO, "Failed to get pipeline object, skipping draw"); return false; } // Get a new descriptor set if any parts have changed if (m_dirty_flags & DIRTY_FLAG_ALL_DESCRIPTOR_SETS && !UpdateDescriptorSet()) { // We can fail to allocate descriptors if we exhaust the pool for this command buffer. WARN_LOG(VIDEO, "Failed to get a descriptor set, executing buffer"); Util::ExecuteCurrentCommandsAndRestoreState(false, false); if (!UpdateDescriptorSet()) { // Something strange going on. ERROR_LOG(VIDEO, "Failed to get descriptor set, skipping draw"); return false; } } // Start render pass if not already started if (!InRenderPass()) BeginRenderPass(); // Re-bind parts of the pipeline VkCommandBuffer command_buffer = g_command_buffer_mgr->GetCurrentCommandBuffer(); if (m_dirty_flags & DIRTY_FLAG_PIPELINE_BINDING || rebind_all) vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipeline_object); if (m_dirty_flags & DIRTY_FLAG_VERTEX_BUFFER || rebind_all) vkCmdBindVertexBuffers(command_buffer, 0, 1, &m_vertex_buffer, &m_vertex_buffer_offset); if (m_dirty_flags & DIRTY_FLAG_INDEX_BUFFER || rebind_all) vkCmdBindIndexBuffer(command_buffer, m_index_buffer, m_index_buffer_offset, m_index_type); if (m_dirty_flags & DIRTY_FLAG_DESCRIPTOR_SET_BINDING || rebind_all) { vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipeline_state.pipeline_layout, 0, m_num_active_descriptor_sets, m_descriptor_sets.data(), NUM_UBO_DESCRIPTOR_SET_BINDINGS, m_bindings.uniform_buffer_offsets.data()); } else if (m_dirty_flags & DIRTY_FLAG_DYNAMIC_OFFSETS) { vkCmdBindDescriptorSets( command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipeline_state.pipeline_layout, DESCRIPTOR_SET_BIND_POINT_UNIFORM_BUFFERS, 1, &m_descriptor_sets[DESCRIPTOR_SET_BIND_POINT_UNIFORM_BUFFERS], NUM_UBO_DESCRIPTOR_SET_BINDINGS, m_bindings.uniform_buffer_offsets.data()); } if (m_dirty_flags & DIRTY_FLAG_VIEWPORT || rebind_all) vkCmdSetViewport(command_buffer, 0, 1, &m_viewport); if (m_dirty_flags & DIRTY_FLAG_SCISSOR || rebind_all) vkCmdSetScissor(command_buffer, 0, 1, &m_scissor); m_dirty_flags = 0; return true; }