Browse Source

[Pipelines/ GL/ VK] Prevent GPU draw call if CBUF binding fails (cbuf0 error handling)

pull/2/head
Bix 8 months ago
committed by crueter
parent
commit
edabd49384
  1. 3
      src/video_core/buffer_cache/buffer_cache.h
  2. 2
      src/video_core/buffer_cache/buffer_cache_base.h
  3. 6
      src/video_core/renderer_opengl/gl_graphics_pipeline.cpp
  4. 10
      src/video_core/renderer_opengl/gl_graphics_pipeline.h
  5. 3
      src/video_core/renderer_opengl/gl_rasterizer.cpp
  6. 16
      src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
  7. 10
      src/video_core/renderer_vulkan/vk_graphics_pipeline.h
  8. 3
      src/video_core/renderer_vulkan/vk_rasterizer.cpp

3
src/video_core/buffer_cache/buffer_cache.h

@ -416,7 +416,7 @@ void BufferCache<P>::UnbindGraphicsStorageBuffers(size_t stage) {
} }
template <class P> template <class P>
void BufferCache<P>::BindGraphicsStorageBuffer(size_t stage, size_t ssbo_index, u32 cbuf_index,
bool BufferCache<P>::BindGraphicsStorageBuffer(size_t stage, size_t ssbo_index, u32 cbuf_index,
u32 cbuf_offset, bool is_written) { u32 cbuf_offset, bool is_written) {
channel_state->enabled_storage_buffers[stage] |= 1U << ssbo_index; channel_state->enabled_storage_buffers[stage] |= 1U << ssbo_index;
channel_state->written_storage_buffers[stage] |= (is_written ? 1U : 0U) << ssbo_index; channel_state->written_storage_buffers[stage] |= (is_written ? 1U : 0U) << ssbo_index;
@ -425,6 +425,7 @@ void BufferCache<P>::BindGraphicsStorageBuffer(size_t stage, size_t ssbo_index,
const GPUVAddr ssbo_addr = cbufs.const_buffers[cbuf_index].address + cbuf_offset; const GPUVAddr ssbo_addr = cbufs.const_buffers[cbuf_index].address + cbuf_offset;
channel_state->storage_buffers[stage][ssbo_index] = channel_state->storage_buffers[stage][ssbo_index] =
StorageBufferBinding(ssbo_addr, cbuf_index, is_written); StorageBufferBinding(ssbo_addr, cbuf_index, is_written);
return (channel_state->storage_buffers[stage][ssbo_index].buffer_id != NULL_BUFFER_ID);
} }
template <class P> template <class P>

2
src/video_core/buffer_cache/buffer_cache_base.h

@ -235,7 +235,7 @@ public:
void UnbindGraphicsStorageBuffers(size_t stage); void UnbindGraphicsStorageBuffers(size_t stage);
void BindGraphicsStorageBuffer(size_t stage, size_t ssbo_index, u32 cbuf_index, u32 cbuf_offset,
bool BindGraphicsStorageBuffer(size_t stage, size_t ssbo_index, u32 cbuf_index, u32 cbuf_offset,
bool is_written); bool is_written);
void UnbindGraphicsTextureBuffers(size_t stage); void UnbindGraphicsTextureBuffers(size_t stage);

6
src/video_core/renderer_opengl/gl_graphics_pipeline.cpp

@ -128,7 +128,7 @@ bool Passes(const std::array<Shader::Info, 5>& stage_infos, u32 enabled_mask) {
return true; return true;
} }
using ConfigureFuncPtr = void (*)(GraphicsPipeline*, bool);
using ConfigureFuncPtr = bool (*)(GraphicsPipeline*, bool);
template <typename Spec, typename... Specs> template <typename Spec, typename... Specs>
ConfigureFuncPtr FindSpec(const std::array<Shader::Info, 5>& stage_infos, u32 enabled_mask) { ConfigureFuncPtr FindSpec(const std::array<Shader::Info, 5>& stage_infos, u32 enabled_mask) {
@ -275,7 +275,7 @@ GraphicsPipeline::GraphicsPipeline(const Device& device, TextureCache& texture_c
} }
template <typename Spec> template <typename Spec>
void GraphicsPipeline::ConfigureImpl(bool is_indexed) {
bool GraphicsPipeline::ConfigureImpl(bool is_indexed) {
std::array<VideoCommon::ImageViewInOut, MAX_TEXTURES + MAX_IMAGES> views; std::array<VideoCommon::ImageViewInOut, MAX_TEXTURES + MAX_IMAGES> views;
std::array<VideoCommon::SamplerId, MAX_TEXTURES> samplers; std::array<VideoCommon::SamplerId, MAX_TEXTURES> samplers;
size_t views_index{}; size_t views_index{};
@ -556,6 +556,8 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) {
if (image_binding != 0) { if (image_binding != 0) {
glBindImageTextures(0, image_binding, images.data()); glBindImageTextures(0, image_binding, images.data());
} }
return true;
} }
void GraphicsPipeline::ConfigureTransformFeedbackImpl() const { void GraphicsPipeline::ConfigureTransformFeedbackImpl() const {

10
src/video_core/renderer_opengl/gl_graphics_pipeline.h

@ -80,8 +80,8 @@ public:
const std::array<const Shader::Info*, 5>& infos, const std::array<const Shader::Info*, 5>& infos,
const GraphicsPipelineKey& key_, bool force_context_flush = false); const GraphicsPipelineKey& key_, bool force_context_flush = false);
void Configure(bool is_indexed) {
configure_func(this, is_indexed);
bool Configure(bool is_indexed) {
return configure_func(this, is_indexed);
} }
void ConfigureTransformFeedback() const { void ConfigureTransformFeedback() const {
@ -107,7 +107,7 @@ public:
template <typename Spec> template <typename Spec>
static auto MakeConfigureSpecFunc() { static auto MakeConfigureSpecFunc() {
return [](GraphicsPipeline* pipeline, bool is_indexed) { return [](GraphicsPipeline* pipeline, bool is_indexed) {
pipeline->ConfigureImpl<Spec>(is_indexed);
return pipeline->ConfigureImpl<Spec>(is_indexed);
}; };
} }
@ -118,7 +118,7 @@ public:
private: private:
template <typename Spec> template <typename Spec>
void ConfigureImpl(bool is_indexed);
bool ConfigureImpl(bool is_indexed);
void ConfigureTransformFeedbackImpl() const; void ConfigureTransformFeedbackImpl() const;
@ -134,7 +134,7 @@ private:
StateTracker& state_tracker; StateTracker& state_tracker;
const GraphicsPipelineKey key; const GraphicsPipelineKey key;
void (*configure_func)(GraphicsPipeline*, bool){};
bool (*configure_func)(GraphicsPipeline*, bool){};
std::array<OGLProgram, 5> source_programs; std::array<OGLProgram, 5> source_programs;
std::array<OGLAssemblyProgram, 5> assembly_programs; std::array<OGLAssemblyProgram, 5> assembly_programs;

3
src/video_core/renderer_opengl/gl_rasterizer.cpp

@ -250,7 +250,8 @@ void RasterizerOpenGL::PrepareDraw(bool is_indexed, Func&& draw_func) {
program_manager.LocalMemoryWarmup(); program_manager.LocalMemoryWarmup();
} }
pipeline->SetEngine(maxwell3d, gpu_memory); pipeline->SetEngine(maxwell3d, gpu_memory);
pipeline->Configure(is_indexed);
if (!pipeline->Configure(is_indexed))
return;
SyncState(); SyncState();

16
src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp

@ -175,7 +175,7 @@ bool Passes(const std::array<vk::ShaderModule, NUM_STAGES>& modules,
return true; return true;
} }
using ConfigureFuncPtr = void (*)(GraphicsPipeline*, bool);
using ConfigureFuncPtr = bool (*)(GraphicsPipeline*, bool);
template <typename Spec, typename... Specs> template <typename Spec, typename... Specs>
ConfigureFuncPtr FindSpec(const std::array<vk::ShaderModule, NUM_STAGES>& modules, ConfigureFuncPtr FindSpec(const std::array<vk::ShaderModule, NUM_STAGES>& modules,
@ -302,7 +302,7 @@ void GraphicsPipeline::AddTransition(GraphicsPipeline* transition) {
} }
template <typename Spec> template <typename Spec>
void GraphicsPipeline::ConfigureImpl(bool is_indexed) {
bool GraphicsPipeline::ConfigureImpl(bool is_indexed) {
std::array<VideoCommon::ImageViewInOut, MAX_IMAGE_ELEMENTS> views; std::array<VideoCommon::ImageViewInOut, MAX_IMAGE_ELEMENTS> views;
std::array<VideoCommon::SamplerId, MAX_IMAGE_ELEMENTS> samplers; std::array<VideoCommon::SamplerId, MAX_IMAGE_ELEMENTS> samplers;
size_t sampler_index{}; size_t sampler_index{};
@ -321,8 +321,9 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) {
size_t ssbo_index{}; size_t ssbo_index{};
for (const auto& desc : info.storage_buffers_descriptors) { for (const auto& desc : info.storage_buffers_descriptors) {
ASSERT(desc.count == 1); ASSERT(desc.count == 1);
buffer_cache.BindGraphicsStorageBuffer(stage, ssbo_index, desc.cbuf_index,
desc.cbuf_offset, desc.is_written);
if (!buffer_cache.BindGraphicsStorageBuffer(stage, ssbo_index, desc.cbuf_index,
desc.cbuf_offset, desc.is_written))
return false;
++ssbo_index; ++ssbo_index;
} }
} }
@ -382,6 +383,8 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) {
add_image(desc, desc.is_written); add_image(desc, desc.is_written);
} }
} }
return true;
}}; }};
if constexpr (Spec::enabled_stages[0]) { if constexpr (Spec::enabled_stages[0]) {
config_stage(0); config_stage(0);
@ -396,7 +399,8 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) {
config_stage(3); config_stage(3);
} }
if constexpr (Spec::enabled_stages[4]) { if constexpr (Spec::enabled_stages[4]) {
config_stage(4);
if (!config_stage(4))
return false;
} }
texture_cache.FillGraphicsImageViews<Spec::has_images>(std::span(views.data(), view_index)); texture_cache.FillGraphicsImageViews<Spec::has_images>(std::span(views.data(), view_index));
@ -490,6 +494,8 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) {
texture_cache.UpdateRenderTargets(false); texture_cache.UpdateRenderTargets(false);
texture_cache.CheckFeedbackLoop(views); texture_cache.CheckFeedbackLoop(views);
ConfigureDraw(rescaling, render_area); ConfigureDraw(rescaling, render_area);
return true;
} }
void GraphicsPipeline::ConfigureDraw(const RescalingPushConstant& rescaling, void GraphicsPipeline::ConfigureDraw(const RescalingPushConstant& rescaling,

10
src/video_core/renderer_vulkan/vk_graphics_pipeline.h

@ -86,8 +86,8 @@ public:
void AddTransition(GraphicsPipeline* transition); void AddTransition(GraphicsPipeline* transition);
void Configure(bool is_indexed) {
configure_func(this, is_indexed);
bool Configure(bool is_indexed) {
return configure_func(this, is_indexed);
} }
[[nodiscard]] GraphicsPipeline* Next(const GraphicsPipelineCacheKey& current_key) noexcept { [[nodiscard]] GraphicsPipeline* Next(const GraphicsPipelineCacheKey& current_key) noexcept {
@ -105,7 +105,7 @@ public:
template <typename Spec> template <typename Spec>
static auto MakeConfigureSpecFunc() { static auto MakeConfigureSpecFunc() {
return [](GraphicsPipeline* pl, bool is_indexed) { pl->ConfigureImpl<Spec>(is_indexed); };
return [](GraphicsPipeline* pl, bool is_indexed) { return pl->ConfigureImpl<Spec>(is_indexed); };
} }
void SetEngine(Tegra::Engines::Maxwell3D* maxwell3d_, Tegra::MemoryManager* gpu_memory_) { void SetEngine(Tegra::Engines::Maxwell3D* maxwell3d_, Tegra::MemoryManager* gpu_memory_) {
@ -115,7 +115,7 @@ public:
private: private:
template <typename Spec> template <typename Spec>
void ConfigureImpl(bool is_indexed);
bool ConfigureImpl(bool is_indexed);
void ConfigureDraw(const RescalingPushConstant& rescaling, void ConfigureDraw(const RescalingPushConstant& rescaling,
const RenderAreaPushConstant& render_are); const RenderAreaPushConstant& render_are);
@ -134,7 +134,7 @@ private:
Scheduler& scheduler; Scheduler& scheduler;
GuestDescriptorQueue& guest_descriptor_queue; GuestDescriptorQueue& guest_descriptor_queue;
void (*configure_func)(GraphicsPipeline*, bool){};
bool (*configure_func)(GraphicsPipeline*, bool){};
std::vector<GraphicsPipelineCacheKey> transition_keys; std::vector<GraphicsPipelineCacheKey> transition_keys;
std::vector<GraphicsPipeline*> transitions; std::vector<GraphicsPipeline*> transitions;

3
src/video_core/renderer_vulkan/vk_rasterizer.cpp

@ -226,7 +226,8 @@ void RasterizerVulkan::PrepareDraw(bool is_indexed, Func&& draw_func) {
std::scoped_lock lock{buffer_cache.mutex, texture_cache.mutex}; std::scoped_lock lock{buffer_cache.mutex, texture_cache.mutex};
// update engine as channel may be different. // update engine as channel may be different.
pipeline->SetEngine(maxwell3d, gpu_memory); pipeline->SetEngine(maxwell3d, gpu_memory);
pipeline->Configure(is_indexed);
if (!pipeline->Configure(is_indexed))
return;
UpdateDynamicStates(); UpdateDynamicStates();

Loading…
Cancel
Save