diff options
| author | 2022-12-06 22:32:59 +0100 | |
|---|---|---|
| committer | 2023-01-01 16:43:58 -0500 | |
| commit | 8d694701bcd97c3766692dff2a9b4ec2f3a64ebd (patch) | |
| tree | 6fe6f656a60c830c1114e4da806359ca1b649009 /src | |
| parent | Vulkan: Add other additional pipeline specs (diff) | |
| download | yuzu-8d694701bcd97c3766692dff2a9b4ec2f3a64ebd.tar.gz yuzu-8d694701bcd97c3766692dff2a9b4ec2f3a64ebd.tar.xz yuzu-8d694701bcd97c3766692dff2a9b4ec2f3a64ebd.zip | |
MacroHLE: Add OpenGL Support
Diffstat (limited to 'src')
6 files changed, 107 insertions, 39 deletions
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl.cpp b/src/shader_recompiler/backend/glsl/emit_glsl.cpp index e8a4390f6..d91e04446 100644 --- a/src/shader_recompiler/backend/glsl/emit_glsl.cpp +++ b/src/shader_recompiler/backend/glsl/emit_glsl.cpp | |||
| @@ -219,7 +219,7 @@ std::string EmitGLSL(const Profile& profile, const RuntimeInfo& runtime_info, IR | |||
| 219 | EmitContext ctx{program, bindings, profile, runtime_info}; | 219 | EmitContext ctx{program, bindings, profile, runtime_info}; |
| 220 | Precolor(program); | 220 | Precolor(program); |
| 221 | EmitCode(ctx, program); | 221 | EmitCode(ctx, program); |
| 222 | const std::string version{fmt::format("#version 450{}\n", GlslVersionSpecifier(ctx))}; | 222 | const std::string version{fmt::format("#version 460{}\n", GlslVersionSpecifier(ctx))}; |
| 223 | ctx.header.insert(0, version); | 223 | ctx.header.insert(0, version); |
| 224 | if (program.shared_memory_size > 0) { | 224 | if (program.shared_memory_size > 0) { |
| 225 | const auto requested_size{program.shared_memory_size}; | 225 | const auto requested_size{program.shared_memory_size}; |
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_context_get_set.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_context_get_set.cpp index 39579cf5d..25106da67 100644 --- a/src/shader_recompiler/backend/glsl/emit_glsl_context_get_set.cpp +++ b/src/shader_recompiler/backend/glsl/emit_glsl_context_get_set.cpp | |||
| @@ -234,6 +234,12 @@ void EmitGetAttribute(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr, | |||
| 234 | case IR::Attribute::FrontFace: | 234 | case IR::Attribute::FrontFace: |
| 235 | ctx.AddF32("{}=itof(gl_FrontFacing?-1:0);", inst); | 235 | ctx.AddF32("{}=itof(gl_FrontFacing?-1:0);", inst); |
| 236 | break; | 236 | break; |
| 237 | case IR::Attribute::BaseInstance: | ||
| 238 | ctx.AddF32("{}=itof(gl_BaseInstance);", inst); | ||
| 239 | break; | ||
| 240 | case IR::Attribute::BaseVertex: | ||
| 241 | ctx.AddF32("{}=itof(gl_BaseVertex);", inst); | ||
| 242 | break; | ||
| 237 | default: | 243 | default: |
| 238 | throw NotImplementedException("Get attribute {}", attr); | 244 | throw NotImplementedException("Get attribute {}", attr); |
| 239 | } | 245 | } |
| @@ -250,6 +256,12 @@ void EmitGetAttributeU32(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr, s | |||
| 250 | case IR::Attribute::VertexId: | 256 | case IR::Attribute::VertexId: |
| 251 | ctx.AddU32("{}=uint(gl_VertexID);", inst); | 257 | ctx.AddU32("{}=uint(gl_VertexID);", inst); |
| 252 | break; | 258 | break; |
| 259 | case IR::Attribute::BaseInstance: | ||
| 260 | ctx.AddU32("{}=uint(gl_BaseInstance);", inst); | ||
| 261 | break; | ||
| 262 | case IR::Attribute::BaseVertex: | ||
| 263 | ctx.AddU32("{}=uint(gl_BaseVertex);", inst); | ||
| 264 | break; | ||
| 253 | default: | 265 | default: |
| 254 | throw NotImplementedException("Get U32 attribute {}", attr); | 266 | throw NotImplementedException("Get U32 attribute {}", attr); |
| 255 | } | 267 | } |
diff --git a/src/video_core/renderer_opengl/gl_graphics_pipeline.h b/src/video_core/renderer_opengl/gl_graphics_pipeline.h index ea53ddb46..1c06b3655 100644 --- a/src/video_core/renderer_opengl/gl_graphics_pipeline.h +++ b/src/video_core/renderer_opengl/gl_graphics_pipeline.h | |||
| @@ -40,6 +40,7 @@ struct GraphicsPipelineKey { | |||
| 40 | BitField<6, 2, Maxwell::Tessellation::DomainType> tessellation_primitive; | 40 | BitField<6, 2, Maxwell::Tessellation::DomainType> tessellation_primitive; |
| 41 | BitField<8, 2, Maxwell::Tessellation::Spacing> tessellation_spacing; | 41 | BitField<8, 2, Maxwell::Tessellation::Spacing> tessellation_spacing; |
| 42 | BitField<10, 1, u32> tessellation_clockwise; | 42 | BitField<10, 1, u32> tessellation_clockwise; |
| 43 | BitField<11, 3, Tegra::Engines::Maxwell3D::EngineHint> app_stage; | ||
| 43 | }; | 44 | }; |
| 44 | std::array<u32, 3> padding; | 45 | std::array<u32, 3> padding; |
| 45 | VideoCommon::TransformFeedbackState xfb_state; | 46 | VideoCommon::TransformFeedbackState xfb_state; |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index a44b8c454..0807d0b88 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp | |||
| @@ -202,7 +202,8 @@ void RasterizerOpenGL::Clear(u32 layer_count) { | |||
| 202 | ++num_queued_commands; | 202 | ++num_queued_commands; |
| 203 | } | 203 | } |
| 204 | 204 | ||
| 205 | void RasterizerOpenGL::Draw(bool is_indexed, u32 instance_count) { | 205 | template <typename Func> |
| 206 | void RasterizerOpenGL::PrepareDraw(bool is_indexed, Func&& draw_func) { | ||
| 206 | MICROPROFILE_SCOPE(OpenGL_Drawing); | 207 | MICROPROFILE_SCOPE(OpenGL_Drawing); |
| 207 | 208 | ||
| 208 | SCOPE_EXIT({ gpu.TickWork(); }); | 209 | SCOPE_EXIT({ gpu.TickWork(); }); |
| @@ -226,48 +227,97 @@ void RasterizerOpenGL::Draw(bool is_indexed, u32 instance_count) { | |||
| 226 | const GLenum primitive_mode = MaxwellToGL::PrimitiveTopology(draw_state.topology); | 227 | const GLenum primitive_mode = MaxwellToGL::PrimitiveTopology(draw_state.topology); |
| 227 | BeginTransformFeedback(pipeline, primitive_mode); | 228 | BeginTransformFeedback(pipeline, primitive_mode); |
| 228 | 229 | ||
| 229 | const GLuint base_instance = static_cast<GLuint>(draw_state.base_instance); | 230 | draw_func(primitive_mode); |
| 230 | const GLsizei num_instances = static_cast<GLsizei>(instance_count); | 231 | |
| 231 | if (is_indexed) { | ||
| 232 | const GLint base_vertex = static_cast<GLint>(draw_state.base_index); | ||
| 233 | const GLsizei num_vertices = static_cast<GLsizei>(draw_state.index_buffer.count); | ||
| 234 | const GLvoid* const offset = buffer_cache_runtime.IndexOffset(); | ||
| 235 | const GLenum format = MaxwellToGL::IndexFormat(draw_state.index_buffer.format); | ||
| 236 | if (num_instances == 1 && base_instance == 0 && base_vertex == 0) { | ||
| 237 | glDrawElements(primitive_mode, num_vertices, format, offset); | ||
| 238 | } else if (num_instances == 1 && base_instance == 0) { | ||
| 239 | glDrawElementsBaseVertex(primitive_mode, num_vertices, format, offset, base_vertex); | ||
| 240 | } else if (base_vertex == 0 && base_instance == 0) { | ||
| 241 | glDrawElementsInstanced(primitive_mode, num_vertices, format, offset, num_instances); | ||
| 242 | } else if (base_vertex == 0) { | ||
| 243 | glDrawElementsInstancedBaseInstance(primitive_mode, num_vertices, format, offset, | ||
| 244 | num_instances, base_instance); | ||
| 245 | } else if (base_instance == 0) { | ||
| 246 | glDrawElementsInstancedBaseVertex(primitive_mode, num_vertices, format, offset, | ||
| 247 | num_instances, base_vertex); | ||
| 248 | } else { | ||
| 249 | glDrawElementsInstancedBaseVertexBaseInstance(primitive_mode, num_vertices, format, | ||
| 250 | offset, num_instances, base_vertex, | ||
| 251 | base_instance); | ||
| 252 | } | ||
| 253 | } else { | ||
| 254 | const GLint base_vertex = static_cast<GLint>(draw_state.vertex_buffer.first); | ||
| 255 | const GLsizei num_vertices = static_cast<GLsizei>(draw_state.vertex_buffer.count); | ||
| 256 | if (num_instances == 1 && base_instance == 0) { | ||
| 257 | glDrawArrays(primitive_mode, base_vertex, num_vertices); | ||
| 258 | } else if (base_instance == 0) { | ||
| 259 | glDrawArraysInstanced(primitive_mode, base_vertex, num_vertices, num_instances); | ||
| 260 | } else { | ||
| 261 | glDrawArraysInstancedBaseInstance(primitive_mode, base_vertex, num_vertices, | ||
| 262 | num_instances, base_instance); | ||
| 263 | } | ||
| 264 | } | ||
| 265 | EndTransformFeedback(); | 232 | EndTransformFeedback(); |
| 266 | 233 | ||
| 267 | ++num_queued_commands; | 234 | ++num_queued_commands; |
| 268 | has_written_global_memory |= pipeline->WritesGlobalMemory(); | 235 | has_written_global_memory |= pipeline->WritesGlobalMemory(); |
| 269 | } | 236 | } |
| 270 | 237 | ||
| 238 | void RasterizerOpenGL::Draw(bool is_indexed, u32 instance_count) { | ||
| 239 | PrepareDraw(is_indexed, [this, is_indexed, instance_count](GLenum primitive_mode) { | ||
| 240 | const auto& draw_state = maxwell3d->draw_manager->GetDrawState(); | ||
| 241 | const GLuint base_instance = static_cast<GLuint>(draw_state.base_instance); | ||
| 242 | const GLsizei num_instances = static_cast<GLsizei>(instance_count); | ||
| 243 | if (is_indexed) { | ||
| 244 | const GLint base_vertex = static_cast<GLint>(draw_state.base_index); | ||
| 245 | const GLsizei num_vertices = static_cast<GLsizei>(draw_state.index_buffer.count); | ||
| 246 | const GLvoid* const offset = buffer_cache_runtime.IndexOffset(); | ||
| 247 | const GLenum format = MaxwellToGL::IndexFormat(draw_state.index_buffer.format); | ||
| 248 | if (num_instances == 1 && base_instance == 0 && base_vertex == 0) { | ||
| 249 | glDrawElements(primitive_mode, num_vertices, format, offset); | ||
| 250 | } else if (num_instances == 1 && base_instance == 0) { | ||
| 251 | glDrawElementsBaseVertex(primitive_mode, num_vertices, format, offset, base_vertex); | ||
| 252 | } else if (base_vertex == 0 && base_instance == 0) { | ||
| 253 | glDrawElementsInstanced(primitive_mode, num_vertices, format, offset, | ||
| 254 | num_instances); | ||
| 255 | } else if (base_vertex == 0) { | ||
| 256 | glDrawElementsInstancedBaseInstance(primitive_mode, num_vertices, format, offset, | ||
| 257 | num_instances, base_instance); | ||
| 258 | } else if (base_instance == 0) { | ||
| 259 | glDrawElementsInstancedBaseVertex(primitive_mode, num_vertices, format, offset, | ||
| 260 | num_instances, base_vertex); | ||
| 261 | } else { | ||
| 262 | glDrawElementsInstancedBaseVertexBaseInstance(primitive_mode, num_vertices, format, | ||
| 263 | offset, num_instances, base_vertex, | ||
| 264 | base_instance); | ||
| 265 | } | ||
| 266 | } else { | ||
| 267 | const GLint base_vertex = static_cast<GLint>(draw_state.vertex_buffer.first); | ||
| 268 | const GLsizei num_vertices = static_cast<GLsizei>(draw_state.vertex_buffer.count); | ||
| 269 | if (num_instances == 1 && base_instance == 0) { | ||
| 270 | glDrawArrays(primitive_mode, base_vertex, num_vertices); | ||
| 271 | } else if (base_instance == 0) { | ||
| 272 | glDrawArraysInstanced(primitive_mode, base_vertex, num_vertices, num_instances); | ||
| 273 | } else { | ||
| 274 | glDrawArraysInstancedBaseInstance(primitive_mode, base_vertex, num_vertices, | ||
| 275 | num_instances, base_instance); | ||
| 276 | } | ||
| 277 | } | ||
| 278 | }); | ||
| 279 | } | ||
| 280 | |||
| 281 | void RasterizerOpenGL::DrawIndirect() { | ||
| 282 | const auto& params = maxwell3d->draw_manager->GetIndirectParams(); | ||
| 283 | buffer_cache.SetDrawIndirect(¶ms); | ||
| 284 | PrepareDraw(params.is_indexed, [this, ¶ms](GLenum primitive_mode) { | ||
| 285 | const auto [buffer, offset] = buffer_cache.GetDrawIndirectBuffer(); | ||
| 286 | const GLvoid* const gl_offset = | ||
| 287 | reinterpret_cast<const GLvoid*>(static_cast<uintptr_t>(offset)); | ||
| 288 | glBindBuffer(GL_DRAW_INDIRECT_BUFFER, buffer->Handle()); | ||
| 289 | if (params.include_count) { | ||
| 290 | const auto [draw_buffer, offset_base] = buffer_cache.GetDrawIndirectCount(); | ||
| 291 | glBindBuffer(GL_PARAMETER_BUFFER, draw_buffer->Handle()); | ||
| 292 | |||
| 293 | if (params.is_indexed) { | ||
| 294 | const GLenum format = MaxwellToGL::IndexFormat(maxwell3d->regs.index_buffer.format); | ||
| 295 | glMultiDrawElementsIndirectCount(primitive_mode, format, gl_offset, | ||
| 296 | static_cast<GLintptr>(offset_base), | ||
| 297 | static_cast<GLsizei>(params.max_draw_counts), | ||
| 298 | static_cast<GLsizei>(params.stride)); | ||
| 299 | } else { | ||
| 300 | glMultiDrawArraysIndirectCount(primitive_mode, gl_offset, | ||
| 301 | static_cast<GLintptr>(offset_base), | ||
| 302 | static_cast<GLsizei>(params.max_draw_counts), | ||
| 303 | static_cast<GLsizei>(params.stride)); | ||
| 304 | } | ||
| 305 | return; | ||
| 306 | } | ||
| 307 | if (params.is_indexed) { | ||
| 308 | const GLenum format = MaxwellToGL::IndexFormat(maxwell3d->regs.index_buffer.format); | ||
| 309 | glMultiDrawElementsIndirect(primitive_mode, format, gl_offset, | ||
| 310 | static_cast<GLsizei>(params.max_draw_counts), | ||
| 311 | static_cast<GLsizei>(params.stride)); | ||
| 312 | } else { | ||
| 313 | glMultiDrawArraysIndirect(primitive_mode, gl_offset, | ||
| 314 | static_cast<GLsizei>(params.max_draw_counts), | ||
| 315 | static_cast<GLsizei>(params.stride)); | ||
| 316 | } | ||
| 317 | }); | ||
| 318 | buffer_cache.SetDrawIndirect(nullptr); | ||
| 319 | } | ||
| 320 | |||
| 271 | void RasterizerOpenGL::DispatchCompute() { | 321 | void RasterizerOpenGL::DispatchCompute() { |
| 272 | ComputePipeline* const pipeline{shader_cache.CurrentComputePipeline()}; | 322 | ComputePipeline* const pipeline{shader_cache.CurrentComputePipeline()}; |
| 273 | if (!pipeline) { | 323 | if (!pipeline) { |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h index fc183c3ca..efd19f880 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.h +++ b/src/video_core/renderer_opengl/gl_rasterizer.h | |||
| @@ -69,6 +69,7 @@ public: | |||
| 69 | ~RasterizerOpenGL() override; | 69 | ~RasterizerOpenGL() override; |
| 70 | 70 | ||
| 71 | void Draw(bool is_indexed, u32 instance_count) override; | 71 | void Draw(bool is_indexed, u32 instance_count) override; |
| 72 | void DrawIndirect() override; | ||
| 72 | void Clear(u32 layer_count) override; | 73 | void Clear(u32 layer_count) override; |
| 73 | void DispatchCompute() override; | 74 | void DispatchCompute() override; |
| 74 | void ResetCounter(VideoCore::QueryType type) override; | 75 | void ResetCounter(VideoCore::QueryType type) override; |
| @@ -121,6 +122,9 @@ private: | |||
| 121 | static constexpr size_t MAX_IMAGES = 48; | 122 | static constexpr size_t MAX_IMAGES = 48; |
| 122 | static constexpr size_t MAX_IMAGE_VIEWS = MAX_TEXTURES + MAX_IMAGES; | 123 | static constexpr size_t MAX_IMAGE_VIEWS = MAX_TEXTURES + MAX_IMAGES; |
| 123 | 124 | ||
| 125 | template <typename Func> | ||
| 126 | void PrepareDraw(bool is_indexed, Func&&); | ||
| 127 | |||
| 124 | /// Syncs state to match guest's | 128 | /// Syncs state to match guest's |
| 125 | void SyncState(); | 129 | void SyncState(); |
| 126 | 130 | ||
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp index f8868a012..bf991afee 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.cpp +++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp | |||
| @@ -51,7 +51,7 @@ using VideoCommon::LoadPipelines; | |||
| 51 | using VideoCommon::SerializePipeline; | 51 | using VideoCommon::SerializePipeline; |
| 52 | using Context = ShaderContext::Context; | 52 | using Context = ShaderContext::Context; |
| 53 | 53 | ||
| 54 | constexpr u32 CACHE_VERSION = 7; | 54 | constexpr u32 CACHE_VERSION = 8; |
| 55 | 55 | ||
| 56 | template <typename Container> | 56 | template <typename Container> |
| 57 | auto MakeSpan(Container& container) { | 57 | auto MakeSpan(Container& container) { |
| @@ -350,6 +350,7 @@ GraphicsPipeline* ShaderCache::CurrentGraphicsPipeline() { | |||
| 350 | regs.tessellation.params.output_primitives.Value() == | 350 | regs.tessellation.params.output_primitives.Value() == |
| 351 | Maxwell::Tessellation::OutputPrimitives::Triangles_CW); | 351 | Maxwell::Tessellation::OutputPrimitives::Triangles_CW); |
| 352 | graphics_key.xfb_enabled.Assign(regs.transform_feedback_enabled != 0 ? 1 : 0); | 352 | graphics_key.xfb_enabled.Assign(regs.transform_feedback_enabled != 0 ? 1 : 0); |
| 353 | graphics_key.app_stage.Assign(maxwell3d->engine_state); | ||
| 353 | if (graphics_key.xfb_enabled) { | 354 | if (graphics_key.xfb_enabled) { |
| 354 | SetXfbState(graphics_key.xfb_state, regs); | 355 | SetXfbState(graphics_key.xfb_state, regs); |
| 355 | } | 356 | } |