mirror of
https://git.suyu.dev/suyu/suyu.git
synced 2024-11-26 08:42:45 +01:00
MacroHLE: Add OpenGL Support
This commit is contained in:
parent
4c82e47edd
commit
8d694701bc
6 changed files with 107 additions and 39 deletions
|
@ -219,7 +219,7 @@ std::string EmitGLSL(const Profile& profile, const RuntimeInfo& runtime_info, IR
|
||||||
EmitContext ctx{program, bindings, profile, runtime_info};
|
EmitContext ctx{program, bindings, profile, runtime_info};
|
||||||
Precolor(program);
|
Precolor(program);
|
||||||
EmitCode(ctx, program);
|
EmitCode(ctx, program);
|
||||||
const std::string version{fmt::format("#version 450{}\n", GlslVersionSpecifier(ctx))};
|
const std::string version{fmt::format("#version 460{}\n", GlslVersionSpecifier(ctx))};
|
||||||
ctx.header.insert(0, version);
|
ctx.header.insert(0, version);
|
||||||
if (program.shared_memory_size > 0) {
|
if (program.shared_memory_size > 0) {
|
||||||
const auto requested_size{program.shared_memory_size};
|
const auto requested_size{program.shared_memory_size};
|
||||||
|
|
|
@ -234,6 +234,12 @@ void EmitGetAttribute(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr,
|
||||||
case IR::Attribute::FrontFace:
|
case IR::Attribute::FrontFace:
|
||||||
ctx.AddF32("{}=itof(gl_FrontFacing?-1:0);", inst);
|
ctx.AddF32("{}=itof(gl_FrontFacing?-1:0);", inst);
|
||||||
break;
|
break;
|
||||||
|
case IR::Attribute::BaseInstance:
|
||||||
|
ctx.AddF32("{}=itof(gl_BaseInstance);", inst);
|
||||||
|
break;
|
||||||
|
case IR::Attribute::BaseVertex:
|
||||||
|
ctx.AddF32("{}=itof(gl_BaseVertex);", inst);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
throw NotImplementedException("Get attribute {}", attr);
|
throw NotImplementedException("Get attribute {}", attr);
|
||||||
}
|
}
|
||||||
|
@ -250,6 +256,12 @@ void EmitGetAttributeU32(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr, s
|
||||||
case IR::Attribute::VertexId:
|
case IR::Attribute::VertexId:
|
||||||
ctx.AddU32("{}=uint(gl_VertexID);", inst);
|
ctx.AddU32("{}=uint(gl_VertexID);", inst);
|
||||||
break;
|
break;
|
||||||
|
case IR::Attribute::BaseInstance:
|
||||||
|
ctx.AddU32("{}=uint(gl_BaseInstance);", inst);
|
||||||
|
break;
|
||||||
|
case IR::Attribute::BaseVertex:
|
||||||
|
ctx.AddU32("{}=uint(gl_BaseVertex);", inst);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
throw NotImplementedException("Get U32 attribute {}", attr);
|
throw NotImplementedException("Get U32 attribute {}", attr);
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,6 +40,7 @@ struct GraphicsPipelineKey {
|
||||||
BitField<6, 2, Maxwell::Tessellation::DomainType> tessellation_primitive;
|
BitField<6, 2, Maxwell::Tessellation::DomainType> tessellation_primitive;
|
||||||
BitField<8, 2, Maxwell::Tessellation::Spacing> tessellation_spacing;
|
BitField<8, 2, Maxwell::Tessellation::Spacing> tessellation_spacing;
|
||||||
BitField<10, 1, u32> tessellation_clockwise;
|
BitField<10, 1, u32> tessellation_clockwise;
|
||||||
|
BitField<11, 3, Tegra::Engines::Maxwell3D::EngineHint> app_stage;
|
||||||
};
|
};
|
||||||
std::array<u32, 3> padding;
|
std::array<u32, 3> padding;
|
||||||
VideoCommon::TransformFeedbackState xfb_state;
|
VideoCommon::TransformFeedbackState xfb_state;
|
||||||
|
|
|
@ -202,7 +202,8 @@ void RasterizerOpenGL::Clear(u32 layer_count) {
|
||||||
++num_queued_commands;
|
++num_queued_commands;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerOpenGL::Draw(bool is_indexed, u32 instance_count) {
|
template <typename Func>
|
||||||
|
void RasterizerOpenGL::PrepareDraw(bool is_indexed, Func&& draw_func) {
|
||||||
MICROPROFILE_SCOPE(OpenGL_Drawing);
|
MICROPROFILE_SCOPE(OpenGL_Drawing);
|
||||||
|
|
||||||
SCOPE_EXIT({ gpu.TickWork(); });
|
SCOPE_EXIT({ gpu.TickWork(); });
|
||||||
|
@ -226,48 +227,97 @@ void RasterizerOpenGL::Draw(bool is_indexed, u32 instance_count) {
|
||||||
const GLenum primitive_mode = MaxwellToGL::PrimitiveTopology(draw_state.topology);
|
const GLenum primitive_mode = MaxwellToGL::PrimitiveTopology(draw_state.topology);
|
||||||
BeginTransformFeedback(pipeline, primitive_mode);
|
BeginTransformFeedback(pipeline, primitive_mode);
|
||||||
|
|
||||||
const GLuint base_instance = static_cast<GLuint>(draw_state.base_instance);
|
draw_func(primitive_mode);
|
||||||
const GLsizei num_instances = static_cast<GLsizei>(instance_count);
|
|
||||||
if (is_indexed) {
|
|
||||||
const GLint base_vertex = static_cast<GLint>(draw_state.base_index);
|
|
||||||
const GLsizei num_vertices = static_cast<GLsizei>(draw_state.index_buffer.count);
|
|
||||||
const GLvoid* const offset = buffer_cache_runtime.IndexOffset();
|
|
||||||
const GLenum format = MaxwellToGL::IndexFormat(draw_state.index_buffer.format);
|
|
||||||
if (num_instances == 1 && base_instance == 0 && base_vertex == 0) {
|
|
||||||
glDrawElements(primitive_mode, num_vertices, format, offset);
|
|
||||||
} else if (num_instances == 1 && base_instance == 0) {
|
|
||||||
glDrawElementsBaseVertex(primitive_mode, num_vertices, format, offset, base_vertex);
|
|
||||||
} else if (base_vertex == 0 && base_instance == 0) {
|
|
||||||
glDrawElementsInstanced(primitive_mode, num_vertices, format, offset, num_instances);
|
|
||||||
} else if (base_vertex == 0) {
|
|
||||||
glDrawElementsInstancedBaseInstance(primitive_mode, num_vertices, format, offset,
|
|
||||||
num_instances, base_instance);
|
|
||||||
} else if (base_instance == 0) {
|
|
||||||
glDrawElementsInstancedBaseVertex(primitive_mode, num_vertices, format, offset,
|
|
||||||
num_instances, base_vertex);
|
|
||||||
} else {
|
|
||||||
glDrawElementsInstancedBaseVertexBaseInstance(primitive_mode, num_vertices, format,
|
|
||||||
offset, num_instances, base_vertex,
|
|
||||||
base_instance);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
const GLint base_vertex = static_cast<GLint>(draw_state.vertex_buffer.first);
|
|
||||||
const GLsizei num_vertices = static_cast<GLsizei>(draw_state.vertex_buffer.count);
|
|
||||||
if (num_instances == 1 && base_instance == 0) {
|
|
||||||
glDrawArrays(primitive_mode, base_vertex, num_vertices);
|
|
||||||
} else if (base_instance == 0) {
|
|
||||||
glDrawArraysInstanced(primitive_mode, base_vertex, num_vertices, num_instances);
|
|
||||||
} else {
|
|
||||||
glDrawArraysInstancedBaseInstance(primitive_mode, base_vertex, num_vertices,
|
|
||||||
num_instances, base_instance);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
EndTransformFeedback();
|
EndTransformFeedback();
|
||||||
|
|
||||||
++num_queued_commands;
|
++num_queued_commands;
|
||||||
has_written_global_memory |= pipeline->WritesGlobalMemory();
|
has_written_global_memory |= pipeline->WritesGlobalMemory();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RasterizerOpenGL::Draw(bool is_indexed, u32 instance_count) {
|
||||||
|
PrepareDraw(is_indexed, [this, is_indexed, instance_count](GLenum primitive_mode) {
|
||||||
|
const auto& draw_state = maxwell3d->draw_manager->GetDrawState();
|
||||||
|
const GLuint base_instance = static_cast<GLuint>(draw_state.base_instance);
|
||||||
|
const GLsizei num_instances = static_cast<GLsizei>(instance_count);
|
||||||
|
if (is_indexed) {
|
||||||
|
const GLint base_vertex = static_cast<GLint>(draw_state.base_index);
|
||||||
|
const GLsizei num_vertices = static_cast<GLsizei>(draw_state.index_buffer.count);
|
||||||
|
const GLvoid* const offset = buffer_cache_runtime.IndexOffset();
|
||||||
|
const GLenum format = MaxwellToGL::IndexFormat(draw_state.index_buffer.format);
|
||||||
|
if (num_instances == 1 && base_instance == 0 && base_vertex == 0) {
|
||||||
|
glDrawElements(primitive_mode, num_vertices, format, offset);
|
||||||
|
} else if (num_instances == 1 && base_instance == 0) {
|
||||||
|
glDrawElementsBaseVertex(primitive_mode, num_vertices, format, offset, base_vertex);
|
||||||
|
} else if (base_vertex == 0 && base_instance == 0) {
|
||||||
|
glDrawElementsInstanced(primitive_mode, num_vertices, format, offset,
|
||||||
|
num_instances);
|
||||||
|
} else if (base_vertex == 0) {
|
||||||
|
glDrawElementsInstancedBaseInstance(primitive_mode, num_vertices, format, offset,
|
||||||
|
num_instances, base_instance);
|
||||||
|
} else if (base_instance == 0) {
|
||||||
|
glDrawElementsInstancedBaseVertex(primitive_mode, num_vertices, format, offset,
|
||||||
|
num_instances, base_vertex);
|
||||||
|
} else {
|
||||||
|
glDrawElementsInstancedBaseVertexBaseInstance(primitive_mode, num_vertices, format,
|
||||||
|
offset, num_instances, base_vertex,
|
||||||
|
base_instance);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const GLint base_vertex = static_cast<GLint>(draw_state.vertex_buffer.first);
|
||||||
|
const GLsizei num_vertices = static_cast<GLsizei>(draw_state.vertex_buffer.count);
|
||||||
|
if (num_instances == 1 && base_instance == 0) {
|
||||||
|
glDrawArrays(primitive_mode, base_vertex, num_vertices);
|
||||||
|
} else if (base_instance == 0) {
|
||||||
|
glDrawArraysInstanced(primitive_mode, base_vertex, num_vertices, num_instances);
|
||||||
|
} else {
|
||||||
|
glDrawArraysInstancedBaseInstance(primitive_mode, base_vertex, num_vertices,
|
||||||
|
num_instances, base_instance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void RasterizerOpenGL::DrawIndirect() {
|
||||||
|
const auto& params = maxwell3d->draw_manager->GetIndirectParams();
|
||||||
|
buffer_cache.SetDrawIndirect(¶ms);
|
||||||
|
PrepareDraw(params.is_indexed, [this, ¶ms](GLenum primitive_mode) {
|
||||||
|
const auto [buffer, offset] = buffer_cache.GetDrawIndirectBuffer();
|
||||||
|
const GLvoid* const gl_offset =
|
||||||
|
reinterpret_cast<const GLvoid*>(static_cast<uintptr_t>(offset));
|
||||||
|
glBindBuffer(GL_DRAW_INDIRECT_BUFFER, buffer->Handle());
|
||||||
|
if (params.include_count) {
|
||||||
|
const auto [draw_buffer, offset_base] = buffer_cache.GetDrawIndirectCount();
|
||||||
|
glBindBuffer(GL_PARAMETER_BUFFER, draw_buffer->Handle());
|
||||||
|
|
||||||
|
if (params.is_indexed) {
|
||||||
|
const GLenum format = MaxwellToGL::IndexFormat(maxwell3d->regs.index_buffer.format);
|
||||||
|
glMultiDrawElementsIndirectCount(primitive_mode, format, gl_offset,
|
||||||
|
static_cast<GLintptr>(offset_base),
|
||||||
|
static_cast<GLsizei>(params.max_draw_counts),
|
||||||
|
static_cast<GLsizei>(params.stride));
|
||||||
|
} else {
|
||||||
|
glMultiDrawArraysIndirectCount(primitive_mode, gl_offset,
|
||||||
|
static_cast<GLintptr>(offset_base),
|
||||||
|
static_cast<GLsizei>(params.max_draw_counts),
|
||||||
|
static_cast<GLsizei>(params.stride));
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (params.is_indexed) {
|
||||||
|
const GLenum format = MaxwellToGL::IndexFormat(maxwell3d->regs.index_buffer.format);
|
||||||
|
glMultiDrawElementsIndirect(primitive_mode, format, gl_offset,
|
||||||
|
static_cast<GLsizei>(params.max_draw_counts),
|
||||||
|
static_cast<GLsizei>(params.stride));
|
||||||
|
} else {
|
||||||
|
glMultiDrawArraysIndirect(primitive_mode, gl_offset,
|
||||||
|
static_cast<GLsizei>(params.max_draw_counts),
|
||||||
|
static_cast<GLsizei>(params.stride));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
buffer_cache.SetDrawIndirect(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
void RasterizerOpenGL::DispatchCompute() {
|
void RasterizerOpenGL::DispatchCompute() {
|
||||||
ComputePipeline* const pipeline{shader_cache.CurrentComputePipeline()};
|
ComputePipeline* const pipeline{shader_cache.CurrentComputePipeline()};
|
||||||
if (!pipeline) {
|
if (!pipeline) {
|
||||||
|
|
|
@ -69,6 +69,7 @@ public:
|
||||||
~RasterizerOpenGL() override;
|
~RasterizerOpenGL() override;
|
||||||
|
|
||||||
void Draw(bool is_indexed, u32 instance_count) override;
|
void Draw(bool is_indexed, u32 instance_count) override;
|
||||||
|
void DrawIndirect() override;
|
||||||
void Clear(u32 layer_count) override;
|
void Clear(u32 layer_count) override;
|
||||||
void DispatchCompute() override;
|
void DispatchCompute() override;
|
||||||
void ResetCounter(VideoCore::QueryType type) override;
|
void ResetCounter(VideoCore::QueryType type) override;
|
||||||
|
@ -121,6 +122,9 @@ private:
|
||||||
static constexpr size_t MAX_IMAGES = 48;
|
static constexpr size_t MAX_IMAGES = 48;
|
||||||
static constexpr size_t MAX_IMAGE_VIEWS = MAX_TEXTURES + MAX_IMAGES;
|
static constexpr size_t MAX_IMAGE_VIEWS = MAX_TEXTURES + MAX_IMAGES;
|
||||||
|
|
||||||
|
template <typename Func>
|
||||||
|
void PrepareDraw(bool is_indexed, Func&&);
|
||||||
|
|
||||||
/// Syncs state to match guest's
|
/// Syncs state to match guest's
|
||||||
void SyncState();
|
void SyncState();
|
||||||
|
|
||||||
|
|
|
@ -51,7 +51,7 @@ using VideoCommon::LoadPipelines;
|
||||||
using VideoCommon::SerializePipeline;
|
using VideoCommon::SerializePipeline;
|
||||||
using Context = ShaderContext::Context;
|
using Context = ShaderContext::Context;
|
||||||
|
|
||||||
constexpr u32 CACHE_VERSION = 7;
|
constexpr u32 CACHE_VERSION = 8;
|
||||||
|
|
||||||
template <typename Container>
|
template <typename Container>
|
||||||
auto MakeSpan(Container& container) {
|
auto MakeSpan(Container& container) {
|
||||||
|
@ -350,6 +350,7 @@ GraphicsPipeline* ShaderCache::CurrentGraphicsPipeline() {
|
||||||
regs.tessellation.params.output_primitives.Value() ==
|
regs.tessellation.params.output_primitives.Value() ==
|
||||||
Maxwell::Tessellation::OutputPrimitives::Triangles_CW);
|
Maxwell::Tessellation::OutputPrimitives::Triangles_CW);
|
||||||
graphics_key.xfb_enabled.Assign(regs.transform_feedback_enabled != 0 ? 1 : 0);
|
graphics_key.xfb_enabled.Assign(regs.transform_feedback_enabled != 0 ? 1 : 0);
|
||||||
|
graphics_key.app_stage.Assign(maxwell3d->engine_state);
|
||||||
if (graphics_key.xfb_enabled) {
|
if (graphics_key.xfb_enabled) {
|
||||||
SetXfbState(graphics_key.xfb_state, regs);
|
SetXfbState(graphics_key.xfb_state, regs);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue