mirror of
				https://git.suyu.dev/suyu/suyu
				synced 2025-11-04 00:49:02 -06:00 
			
		
		
		
	opengl: Fix asynchronous shaders
Wait for shader to build before configuring it, and wait for the shader to build before sharing it with other contexts.
This commit is contained in:
		@@ -237,10 +237,12 @@ GraphicsPipeline::GraphicsPipeline(
 | 
				
			|||||||
    if (key.xfb_enabled && device.UseAssemblyShaders()) {
 | 
					    if (key.xfb_enabled && device.UseAssemblyShaders()) {
 | 
				
			||||||
        GenerateTransformFeedbackState();
 | 
					        GenerateTransformFeedbackState();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    auto func{[this, device, sources, sources_spirv,
 | 
					    const bool in_parallel = thread_worker != nullptr;
 | 
				
			||||||
               shader_notify](ShaderContext::Context*) mutable {
 | 
					    const auto backend = device.GetShaderBackend();
 | 
				
			||||||
 | 
					    auto func{[this, sources = std::move(sources), sources_spirv = std::move(sources_spirv),
 | 
				
			||||||
 | 
					               shader_notify, backend, in_parallel](ShaderContext::Context*) mutable {
 | 
				
			||||||
        for (size_t stage = 0; stage < 5; ++stage) {
 | 
					        for (size_t stage = 0; stage < 5; ++stage) {
 | 
				
			||||||
            switch (device.GetShaderBackend()) {
 | 
					            switch (backend) {
 | 
				
			||||||
            case Settings::ShaderBackend::GLSL:
 | 
					            case Settings::ShaderBackend::GLSL:
 | 
				
			||||||
                if (!sources[stage].empty()) {
 | 
					                if (!sources[stage].empty()) {
 | 
				
			||||||
                    source_programs[stage] = CreateProgram(sources[stage], Stage(stage));
 | 
					                    source_programs[stage] = CreateProgram(sources[stage], Stage(stage));
 | 
				
			||||||
@@ -249,6 +251,10 @@ GraphicsPipeline::GraphicsPipeline(
 | 
				
			|||||||
            case Settings::ShaderBackend::GLASM:
 | 
					            case Settings::ShaderBackend::GLASM:
 | 
				
			||||||
                if (!sources[stage].empty()) {
 | 
					                if (!sources[stage].empty()) {
 | 
				
			||||||
                    assembly_programs[stage] = CompileProgram(sources[stage], AssemblyStage(stage));
 | 
					                    assembly_programs[stage] = CompileProgram(sources[stage], AssemblyStage(stage));
 | 
				
			||||||
 | 
					                    if (in_parallel) {
 | 
				
			||||||
 | 
					                        // Make sure program is built before continuing when building in parallel
 | 
				
			||||||
 | 
					                        glGetString(GL_PROGRAM_ERROR_STRING_NV);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                break;
 | 
					                break;
 | 
				
			||||||
            case Settings::ShaderBackend::SPIRV:
 | 
					            case Settings::ShaderBackend::SPIRV:
 | 
				
			||||||
@@ -258,10 +264,20 @@ GraphicsPipeline::GraphicsPipeline(
 | 
				
			|||||||
                break;
 | 
					                break;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        if (in_parallel && backend != Settings::ShaderBackend::GLASM) {
 | 
				
			||||||
 | 
					            // Make sure programs have built if we are building shaders in parallel
 | 
				
			||||||
 | 
					            for (OGLProgram& program : source_programs) {
 | 
				
			||||||
 | 
					                if (program.handle != 0) {
 | 
				
			||||||
 | 
					                    GLint status{};
 | 
				
			||||||
 | 
					                    glGetProgramiv(program.handle, GL_LINK_STATUS, &status);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        if (shader_notify) {
 | 
					        if (shader_notify) {
 | 
				
			||||||
            shader_notify->MarkShaderComplete();
 | 
					            shader_notify->MarkShaderComplete();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        is_built = true;
 | 
					        is_built = true;
 | 
				
			||||||
 | 
					        built_condvar.notify_one();
 | 
				
			||||||
    }};
 | 
					    }};
 | 
				
			||||||
    if (thread_worker) {
 | 
					    if (thread_worker) {
 | 
				
			||||||
        thread_worker->QueueWork(std::move(func));
 | 
					        thread_worker->QueueWork(std::move(func));
 | 
				
			||||||
@@ -434,6 +450,9 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) {
 | 
				
			|||||||
    buffer_cache.UpdateGraphicsBuffers(is_indexed);
 | 
					    buffer_cache.UpdateGraphicsBuffers(is_indexed);
 | 
				
			||||||
    buffer_cache.BindHostGeometryBuffers(is_indexed);
 | 
					    buffer_cache.BindHostGeometryBuffers(is_indexed);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!is_built.load(std::memory_order::relaxed)) {
 | 
				
			||||||
 | 
					        WaitForBuild();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    if (assembly_programs[0].handle != 0) {
 | 
					    if (assembly_programs[0].handle != 0) {
 | 
				
			||||||
        program_manager.BindAssemblyPrograms(assembly_programs, enabled_stages_mask);
 | 
					        program_manager.BindAssemblyPrograms(assembly_programs, enabled_stages_mask);
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
@@ -545,4 +564,9 @@ void GraphicsPipeline::GenerateTransformFeedbackState() {
 | 
				
			|||||||
    num_xfb_strides = static_cast<GLsizei>(current_stream - xfb_streams.data());
 | 
					    num_xfb_strides = static_cast<GLsizei>(current_stream - xfb_streams.data());
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void GraphicsPipeline::WaitForBuild() {
 | 
				
			||||||
 | 
					    std::unique_lock lock{built_mutex};
 | 
				
			||||||
 | 
					    built_condvar.wait(lock, [this] { return is_built.load(std::memory_order::relaxed); });
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
} // namespace OpenGL
 | 
					} // namespace OpenGL
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -119,6 +119,8 @@ private:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    void GenerateTransformFeedbackState();
 | 
					    void GenerateTransformFeedbackState();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void WaitForBuild();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    TextureCache& texture_cache;
 | 
					    TextureCache& texture_cache;
 | 
				
			||||||
    BufferCache& buffer_cache;
 | 
					    BufferCache& buffer_cache;
 | 
				
			||||||
    Tegra::MemoryManager& gpu_memory;
 | 
					    Tegra::MemoryManager& gpu_memory;
 | 
				
			||||||
@@ -143,13 +145,16 @@ private:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    bool use_storage_buffers{};
 | 
					    bool use_storage_buffers{};
 | 
				
			||||||
    bool writes_global_memory{};
 | 
					    bool writes_global_memory{};
 | 
				
			||||||
    std::atomic_bool is_built{false};
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    static constexpr std::size_t XFB_ENTRY_STRIDE = 3;
 | 
					    static constexpr std::size_t XFB_ENTRY_STRIDE = 3;
 | 
				
			||||||
    GLsizei num_xfb_attribs{};
 | 
					    GLsizei num_xfb_attribs{};
 | 
				
			||||||
    GLsizei num_xfb_strides{};
 | 
					    GLsizei num_xfb_strides{};
 | 
				
			||||||
    std::array<GLint, 128 * XFB_ENTRY_STRIDE * Maxwell::NumTransformFeedbackBuffers> xfb_attribs{};
 | 
					    std::array<GLint, 128 * XFB_ENTRY_STRIDE * Maxwell::NumTransformFeedbackBuffers> xfb_attribs{};
 | 
				
			||||||
    std::array<GLint, Maxwell::NumTransformFeedbackBuffers> xfb_streams{};
 | 
					    std::array<GLint, Maxwell::NumTransformFeedbackBuffers> xfb_streams{};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::mutex built_mutex;
 | 
				
			||||||
 | 
					    std::condition_variable built_condvar;
 | 
				
			||||||
 | 
					    std::atomic_bool is_built{false};
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
} // namespace OpenGL
 | 
					} // namespace OpenGL
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user