summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Fernando Sahmkow2022-12-06 22:32:59 +0100
committerGravatar Fernando Sahmkow2023-01-01 16:43:58 -0500
commit8d694701bcd97c3766692dff2a9b4ec2f3a64ebd (patch)
tree6fe6f656a60c830c1114e4da806359ca1b649009
parentVulkan: Add other additional pipeline specs (diff)
downloadyuzu-8d694701bcd97c3766692dff2a9b4ec2f3a64ebd.tar.gz
yuzu-8d694701bcd97c3766692dff2a9b4ec2f3a64ebd.tar.xz
yuzu-8d694701bcd97c3766692dff2a9b4ec2f3a64ebd.zip
MacroHLE: Add OpenGL Support
-rw-r--r--src/shader_recompiler/backend/glsl/emit_glsl.cpp2
-rw-r--r--src/shader_recompiler/backend/glsl/emit_glsl_context_get_set.cpp12
-rw-r--r--src/video_core/renderer_opengl/gl_graphics_pipeline.h1
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp124
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.h4
-rw-r--r--src/video_core/renderer_opengl/gl_shader_cache.cpp3
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
205void RasterizerOpenGL::Draw(bool is_indexed, u32 instance_count) { 205template <typename Func>
206void 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
238void 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
281void RasterizerOpenGL::DrawIndirect() {
282 const auto& params = maxwell3d->draw_manager->GetIndirectParams();
283 buffer_cache.SetDrawIndirect(&params);
284 PrepareDraw(params.is_indexed, [this, &params](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
271void RasterizerOpenGL::DispatchCompute() { 321void 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;
51using VideoCommon::SerializePipeline; 51using VideoCommon::SerializePipeline;
52using Context = ShaderContext::Context; 52using Context = ShaderContext::Context;
53 53
54constexpr u32 CACHE_VERSION = 7; 54constexpr u32 CACHE_VERSION = 8;
55 55
56template <typename Container> 56template <typename Container>
57auto MakeSpan(Container& container) { 57auto 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 }