1
0
Fork 0
forked from suyu/suyu

OpenGl: Implement Channels.

This commit is contained in:
Fernando Sahmkow 2021-11-07 17:15:28 +01:00
parent 2c62563ab5
commit d7990c159e
9 changed files with 186 additions and 118 deletions

View file

@ -16,7 +16,7 @@
#include "common/microprofile.h" #include "common/microprofile.h"
#include "common/scope_exit.h" #include "common/scope_exit.h"
#include "common/settings.h" #include "common/settings.h"
#include "video_core/control/channel_state.h"
#include "video_core/engines/kepler_compute.h" #include "video_core/engines/kepler_compute.h"
#include "video_core/engines/maxwell_3d.h" #include "video_core/engines/maxwell_3d.h"
#include "video_core/memory_manager.h" #include "video_core/memory_manager.h"
@ -56,9 +56,8 @@ RasterizerOpenGL::RasterizerOpenGL(Core::Frontend::EmuWindow& emu_window_, Tegra
Core::Memory::Memory& cpu_memory_, const Device& device_, Core::Memory::Memory& cpu_memory_, const Device& device_,
ScreenInfo& screen_info_, ProgramManager& program_manager_, ScreenInfo& screen_info_, ProgramManager& program_manager_,
StateTracker& state_tracker_) StateTracker& state_tracker_)
: RasterizerAccelerated(cpu_memory_), gpu(gpu_), maxwell3d(gpu.Maxwell3D()), : RasterizerAccelerated(cpu_memory_), gpu(gpu_), device(device_), screen_info(screen_info_),
kepler_compute(gpu.KeplerCompute()), gpu_memory(gpu.MemoryManager()), device(device_), program_manager(program_manager_), state_tracker(state_tracker_),
screen_info(screen_info_), program_manager(program_manager_), state_tracker(state_tracker_),
texture_cache_runtime(device, program_manager, state_tracker), texture_cache_runtime(device, program_manager, state_tracker),
texture_cache(texture_cache_runtime, *this), buffer_cache_runtime(device), texture_cache(texture_cache_runtime, *this), buffer_cache_runtime(device),
buffer_cache(*this, cpu_memory_, buffer_cache_runtime), buffer_cache(*this, cpu_memory_, buffer_cache_runtime),
@ -70,7 +69,7 @@ RasterizerOpenGL::RasterizerOpenGL(Core::Frontend::EmuWindow& emu_window_, Tegra
RasterizerOpenGL::~RasterizerOpenGL() = default; RasterizerOpenGL::~RasterizerOpenGL() = default;
void RasterizerOpenGL::SyncVertexFormats() { void RasterizerOpenGL::SyncVertexFormats() {
auto& flags = maxwell3d.dirty.flags; auto& flags = maxwell3d->dirty.flags;
if (!flags[Dirty::VertexFormats]) { if (!flags[Dirty::VertexFormats]) {
return; return;
} }
@ -88,7 +87,7 @@ void RasterizerOpenGL::SyncVertexFormats() {
} }
flags[Dirty::VertexFormat0 + index] = false; flags[Dirty::VertexFormat0 + index] = false;
const auto attrib = maxwell3d.regs.vertex_attrib_format[index]; const auto attrib = maxwell3d->regs.vertex_attrib_format[index];
const auto gl_index = static_cast<GLuint>(index); const auto gl_index = static_cast<GLuint>(index);
// Disable constant attributes. // Disable constant attributes.
@ -112,13 +111,13 @@ void RasterizerOpenGL::SyncVertexFormats() {
} }
void RasterizerOpenGL::SyncVertexInstances() { void RasterizerOpenGL::SyncVertexInstances() {
auto& flags = maxwell3d.dirty.flags; auto& flags = maxwell3d->dirty.flags;
if (!flags[Dirty::VertexInstances]) { if (!flags[Dirty::VertexInstances]) {
return; return;
} }
flags[Dirty::VertexInstances] = false; flags[Dirty::VertexInstances] = false;
const auto& regs = maxwell3d.regs; const auto& regs = maxwell3d->regs;
for (std::size_t index = 0; index < NUM_SUPPORTED_VERTEX_ATTRIBUTES; ++index) { for (std::size_t index = 0; index < NUM_SUPPORTED_VERTEX_ATTRIBUTES; ++index) {
if (!flags[Dirty::VertexInstance0 + index]) { if (!flags[Dirty::VertexInstance0 + index]) {
continue; continue;
@ -139,11 +138,11 @@ void RasterizerOpenGL::LoadDiskResources(u64 title_id, std::stop_token stop_load
void RasterizerOpenGL::Clear() { void RasterizerOpenGL::Clear() {
MICROPROFILE_SCOPE(OpenGL_Clears); MICROPROFILE_SCOPE(OpenGL_Clears);
if (!maxwell3d.ShouldExecute()) { if (!maxwell3d->ShouldExecute()) {
return; return;
} }
const auto& regs = maxwell3d.regs; const auto& regs = maxwell3d->regs;
bool use_color{}; bool use_color{};
bool use_depth{}; bool use_depth{};
bool use_stencil{}; bool use_stencil{};
@ -221,17 +220,17 @@ void RasterizerOpenGL::Draw(bool is_indexed, bool is_instanced) {
SyncState(); SyncState();
const GLenum primitive_mode = MaxwellToGL::PrimitiveTopology(maxwell3d.regs.draw.topology); const GLenum primitive_mode = MaxwellToGL::PrimitiveTopology(maxwell3d->regs.draw.topology);
BeginTransformFeedback(pipeline, primitive_mode); BeginTransformFeedback(pipeline, primitive_mode);
const GLuint base_instance = static_cast<GLuint>(maxwell3d.regs.vb_base_instance); const GLuint base_instance = static_cast<GLuint>(maxwell3d->regs.vb_base_instance);
const GLsizei num_instances = const GLsizei num_instances =
static_cast<GLsizei>(is_instanced ? maxwell3d.mme_draw.instance_count : 1); static_cast<GLsizei>(is_instanced ? maxwell3d->mme_draw.instance_count : 1);
if (is_indexed) { if (is_indexed) {
const GLint base_vertex = static_cast<GLint>(maxwell3d.regs.vb_element_base); const GLint base_vertex = static_cast<GLint>(maxwell3d->regs.vb_element_base);
const GLsizei num_vertices = static_cast<GLsizei>(maxwell3d.regs.index_array.count); const GLsizei num_vertices = static_cast<GLsizei>(maxwell3d->regs.index_array.count);
const GLvoid* const offset = buffer_cache_runtime.IndexOffset(); const GLvoid* const offset = buffer_cache_runtime.IndexOffset();
const GLenum format = MaxwellToGL::IndexFormat(maxwell3d.regs.index_array.format); const GLenum format = MaxwellToGL::IndexFormat(maxwell3d->regs.index_array.format);
if (num_instances == 1 && base_instance == 0 && base_vertex == 0) { if (num_instances == 1 && base_instance == 0 && base_vertex == 0) {
glDrawElements(primitive_mode, num_vertices, format, offset); glDrawElements(primitive_mode, num_vertices, format, offset);
} else if (num_instances == 1 && base_instance == 0) { } else if (num_instances == 1 && base_instance == 0) {
@ -250,8 +249,8 @@ void RasterizerOpenGL::Draw(bool is_indexed, bool is_instanced) {
base_instance); base_instance);
} }
} else { } else {
const GLint base_vertex = static_cast<GLint>(maxwell3d.regs.vertex_buffer.first); const GLint base_vertex = static_cast<GLint>(maxwell3d->regs.vertex_buffer.first);
const GLsizei num_vertices = static_cast<GLsizei>(maxwell3d.regs.vertex_buffer.count); const GLsizei num_vertices = static_cast<GLsizei>(maxwell3d->regs.vertex_buffer.count);
if (num_instances == 1 && base_instance == 0) { if (num_instances == 1 && base_instance == 0) {
glDrawArrays(primitive_mode, base_vertex, num_vertices); glDrawArrays(primitive_mode, base_vertex, num_vertices);
} else if (base_instance == 0) { } else if (base_instance == 0) {
@ -273,7 +272,7 @@ void RasterizerOpenGL::DispatchCompute() {
return; return;
} }
pipeline->Configure(); pipeline->Configure();
const auto& qmd{kepler_compute.launch_description}; const auto& qmd{kepler_compute->launch_description};
glDispatchCompute(qmd.grid_dim_x, qmd.grid_dim_y, qmd.grid_dim_z); glDispatchCompute(qmd.grid_dim_x, qmd.grid_dim_y, qmd.grid_dim_z);
++num_queued_commands; ++num_queued_commands;
has_written_global_memory |= pipeline->WritesGlobalMemory(); has_written_global_memory |= pipeline->WritesGlobalMemory();
@ -388,10 +387,10 @@ void RasterizerOpenGL::ModifyGPUMemory(GPUVAddr addr, u64 size) {
void RasterizerOpenGL::SignalSemaphore(GPUVAddr addr, u32 value) { void RasterizerOpenGL::SignalSemaphore(GPUVAddr addr, u32 value) {
if (!gpu.IsAsync()) { if (!gpu.IsAsync()) {
gpu_memory.Write<u32>(addr, value); gpu_memory->Write<u32>(addr, value);
return; return;
} }
auto paddr = gpu_memory.GetPointer(addr); auto paddr = gpu_memory->GetPointer(addr);
fence_manager.SignalSemaphore(paddr, value); fence_manager.SignalSemaphore(paddr, value);
} }
@ -483,12 +482,12 @@ Tegra::Engines::AccelerateDMAInterface& RasterizerOpenGL::AccessAccelerateDMA()
void RasterizerOpenGL::AccelerateInlineToMemory(GPUVAddr address, size_t copy_size, void RasterizerOpenGL::AccelerateInlineToMemory(GPUVAddr address, size_t copy_size,
std::span<u8> memory) { std::span<u8> memory) {
auto cpu_addr = gpu_memory.GpuToCpuAddress(address); auto cpu_addr = gpu_memory->GpuToCpuAddress(address);
if (!cpu_addr) [[unlikely]] { if (!cpu_addr) [[unlikely]] {
gpu_memory.WriteBlock(address, memory.data(), copy_size); gpu_memory->WriteBlock(address, memory.data(), copy_size);
return; return;
} }
gpu_memory.WriteBlockUnsafe(address, memory.data(), copy_size); gpu_memory->WriteBlockUnsafe(address, memory.data(), copy_size);
{ {
std::unique_lock<std::mutex> lock{buffer_cache.mutex}; std::unique_lock<std::mutex> lock{buffer_cache.mutex};
if (!buffer_cache.InlineMemory(*cpu_addr, copy_size, memory)) { if (!buffer_cache.InlineMemory(*cpu_addr, copy_size, memory)) {
@ -551,8 +550,8 @@ void RasterizerOpenGL::SyncState() {
} }
void RasterizerOpenGL::SyncViewport() { void RasterizerOpenGL::SyncViewport() {
auto& flags = maxwell3d.dirty.flags; auto& flags = maxwell3d->dirty.flags;
const auto& regs = maxwell3d.regs; const auto& regs = maxwell3d->regs;
const bool rescale_viewports = flags[VideoCommon::Dirty::RescaleViewports]; const bool rescale_viewports = flags[VideoCommon::Dirty::RescaleViewports];
const bool dirty_viewport = flags[Dirty::Viewports] || rescale_viewports; const bool dirty_viewport = flags[Dirty::Viewports] || rescale_viewports;
@ -657,23 +656,23 @@ void RasterizerOpenGL::SyncViewport() {
} }
void RasterizerOpenGL::SyncDepthClamp() { void RasterizerOpenGL::SyncDepthClamp() {
auto& flags = maxwell3d.dirty.flags; auto& flags = maxwell3d->dirty.flags;
if (!flags[Dirty::DepthClampEnabled]) { if (!flags[Dirty::DepthClampEnabled]) {
return; return;
} }
flags[Dirty::DepthClampEnabled] = false; flags[Dirty::DepthClampEnabled] = false;
oglEnable(GL_DEPTH_CLAMP, maxwell3d.regs.view_volume_clip_control.depth_clamp_disabled == 0); oglEnable(GL_DEPTH_CLAMP, maxwell3d->regs.view_volume_clip_control.depth_clamp_disabled == 0);
} }
void RasterizerOpenGL::SyncClipEnabled(u32 clip_mask) { void RasterizerOpenGL::SyncClipEnabled(u32 clip_mask) {
auto& flags = maxwell3d.dirty.flags; auto& flags = maxwell3d->dirty.flags;
if (!flags[Dirty::ClipDistances] && !flags[VideoCommon::Dirty::Shaders]) { if (!flags[Dirty::ClipDistances] && !flags[VideoCommon::Dirty::Shaders]) {
return; return;
} }
flags[Dirty::ClipDistances] = false; flags[Dirty::ClipDistances] = false;
clip_mask &= maxwell3d.regs.clip_distance_enabled; clip_mask &= maxwell3d->regs.clip_distance_enabled;
if (clip_mask == last_clip_distance_mask) { if (clip_mask == last_clip_distance_mask) {
return; return;
} }
@ -689,8 +688,8 @@ void RasterizerOpenGL::SyncClipCoef() {
} }
void RasterizerOpenGL::SyncCullMode() { void RasterizerOpenGL::SyncCullMode() {
auto& flags = maxwell3d.dirty.flags; auto& flags = maxwell3d->dirty.flags;
const auto& regs = maxwell3d.regs; const auto& regs = maxwell3d->regs;
if (flags[Dirty::CullTest]) { if (flags[Dirty::CullTest]) {
flags[Dirty::CullTest] = false; flags[Dirty::CullTest] = false;
@ -705,23 +704,23 @@ void RasterizerOpenGL::SyncCullMode() {
} }
void RasterizerOpenGL::SyncPrimitiveRestart() { void RasterizerOpenGL::SyncPrimitiveRestart() {
auto& flags = maxwell3d.dirty.flags; auto& flags = maxwell3d->dirty.flags;
if (!flags[Dirty::PrimitiveRestart]) { if (!flags[Dirty::PrimitiveRestart]) {
return; return;
} }
flags[Dirty::PrimitiveRestart] = false; flags[Dirty::PrimitiveRestart] = false;
if (maxwell3d.regs.primitive_restart.enabled) { if (maxwell3d->regs.primitive_restart.enabled) {
glEnable(GL_PRIMITIVE_RESTART); glEnable(GL_PRIMITIVE_RESTART);
glPrimitiveRestartIndex(maxwell3d.regs.primitive_restart.index); glPrimitiveRestartIndex(maxwell3d->regs.primitive_restart.index);
} else { } else {
glDisable(GL_PRIMITIVE_RESTART); glDisable(GL_PRIMITIVE_RESTART);
} }
} }
void RasterizerOpenGL::SyncDepthTestState() { void RasterizerOpenGL::SyncDepthTestState() {
auto& flags = maxwell3d.dirty.flags; auto& flags = maxwell3d->dirty.flags;
const auto& regs = maxwell3d.regs; const auto& regs = maxwell3d->regs;
if (flags[Dirty::DepthMask]) { if (flags[Dirty::DepthMask]) {
flags[Dirty::DepthMask] = false; flags[Dirty::DepthMask] = false;
@ -740,13 +739,13 @@ void RasterizerOpenGL::SyncDepthTestState() {
} }
void RasterizerOpenGL::SyncStencilTestState() { void RasterizerOpenGL::SyncStencilTestState() {
auto& flags = maxwell3d.dirty.flags; auto& flags = maxwell3d->dirty.flags;
if (!flags[Dirty::StencilTest]) { if (!flags[Dirty::StencilTest]) {
return; return;
} }
flags[Dirty::StencilTest] = false; flags[Dirty::StencilTest] = false;
const auto& regs = maxwell3d.regs; const auto& regs = maxwell3d->regs;
oglEnable(GL_STENCIL_TEST, regs.stencil_enable); oglEnable(GL_STENCIL_TEST, regs.stencil_enable);
glStencilFuncSeparate(GL_FRONT, MaxwellToGL::ComparisonOp(regs.stencil_front_func_func), glStencilFuncSeparate(GL_FRONT, MaxwellToGL::ComparisonOp(regs.stencil_front_func_func),
@ -771,23 +770,23 @@ void RasterizerOpenGL::SyncStencilTestState() {
} }
void RasterizerOpenGL::SyncRasterizeEnable() { void RasterizerOpenGL::SyncRasterizeEnable() {
auto& flags = maxwell3d.dirty.flags; auto& flags = maxwell3d->dirty.flags;
if (!flags[Dirty::RasterizeEnable]) { if (!flags[Dirty::RasterizeEnable]) {
return; return;
} }
flags[Dirty::RasterizeEnable] = false; flags[Dirty::RasterizeEnable] = false;
oglEnable(GL_RASTERIZER_DISCARD, maxwell3d.regs.rasterize_enable == 0); oglEnable(GL_RASTERIZER_DISCARD, maxwell3d->regs.rasterize_enable == 0);
} }
void RasterizerOpenGL::SyncPolygonModes() { void RasterizerOpenGL::SyncPolygonModes() {
auto& flags = maxwell3d.dirty.flags; auto& flags = maxwell3d->dirty.flags;
if (!flags[Dirty::PolygonModes]) { if (!flags[Dirty::PolygonModes]) {
return; return;
} }
flags[Dirty::PolygonModes] = false; flags[Dirty::PolygonModes] = false;
const auto& regs = maxwell3d.regs; const auto& regs = maxwell3d->regs;
if (regs.fill_rectangle) { if (regs.fill_rectangle) {
if (!GLAD_GL_NV_fill_rectangle) { if (!GLAD_GL_NV_fill_rectangle) {
LOG_ERROR(Render_OpenGL, "GL_NV_fill_rectangle used and not supported"); LOG_ERROR(Render_OpenGL, "GL_NV_fill_rectangle used and not supported");
@ -820,7 +819,7 @@ void RasterizerOpenGL::SyncPolygonModes() {
} }
void RasterizerOpenGL::SyncColorMask() { void RasterizerOpenGL::SyncColorMask() {
auto& flags = maxwell3d.dirty.flags; auto& flags = maxwell3d->dirty.flags;
if (!flags[Dirty::ColorMasks]) { if (!flags[Dirty::ColorMasks]) {
return; return;
} }
@ -829,7 +828,7 @@ void RasterizerOpenGL::SyncColorMask() {
const bool force = flags[Dirty::ColorMaskCommon]; const bool force = flags[Dirty::ColorMaskCommon];
flags[Dirty::ColorMaskCommon] = false; flags[Dirty::ColorMaskCommon] = false;
const auto& regs = maxwell3d.regs; const auto& regs = maxwell3d->regs;
if (regs.color_mask_common) { if (regs.color_mask_common) {
if (!force && !flags[Dirty::ColorMask0]) { if (!force && !flags[Dirty::ColorMask0]) {
return; return;
@ -854,30 +853,30 @@ void RasterizerOpenGL::SyncColorMask() {
} }
void RasterizerOpenGL::SyncMultiSampleState() { void RasterizerOpenGL::SyncMultiSampleState() {
auto& flags = maxwell3d.dirty.flags; auto& flags = maxwell3d->dirty.flags;
if (!flags[Dirty::MultisampleControl]) { if (!flags[Dirty::MultisampleControl]) {
return; return;
} }
flags[Dirty::MultisampleControl] = false; flags[Dirty::MultisampleControl] = false;
const auto& regs = maxwell3d.regs; const auto& regs = maxwell3d->regs;
oglEnable(GL_SAMPLE_ALPHA_TO_COVERAGE, regs.multisample_control.alpha_to_coverage); oglEnable(GL_SAMPLE_ALPHA_TO_COVERAGE, regs.multisample_control.alpha_to_coverage);
oglEnable(GL_SAMPLE_ALPHA_TO_ONE, regs.multisample_control.alpha_to_one); oglEnable(GL_SAMPLE_ALPHA_TO_ONE, regs.multisample_control.alpha_to_one);
} }
void RasterizerOpenGL::SyncFragmentColorClampState() { void RasterizerOpenGL::SyncFragmentColorClampState() {
auto& flags = maxwell3d.dirty.flags; auto& flags = maxwell3d->dirty.flags;
if (!flags[Dirty::FragmentClampColor]) { if (!flags[Dirty::FragmentClampColor]) {
return; return;
} }
flags[Dirty::FragmentClampColor] = false; flags[Dirty::FragmentClampColor] = false;
glClampColor(GL_CLAMP_FRAGMENT_COLOR, maxwell3d.regs.frag_color_clamp ? GL_TRUE : GL_FALSE); glClampColor(GL_CLAMP_FRAGMENT_COLOR, maxwell3d->regs.frag_color_clamp ? GL_TRUE : GL_FALSE);
} }
void RasterizerOpenGL::SyncBlendState() { void RasterizerOpenGL::SyncBlendState() {
auto& flags = maxwell3d.dirty.flags; auto& flags = maxwell3d->dirty.flags;
const auto& regs = maxwell3d.regs; const auto& regs = maxwell3d->regs;
if (flags[Dirty::BlendColor]) { if (flags[Dirty::BlendColor]) {
flags[Dirty::BlendColor] = false; flags[Dirty::BlendColor] = false;
@ -934,13 +933,13 @@ void RasterizerOpenGL::SyncBlendState() {
} }
void RasterizerOpenGL::SyncLogicOpState() { void RasterizerOpenGL::SyncLogicOpState() {
auto& flags = maxwell3d.dirty.flags; auto& flags = maxwell3d->dirty.flags;
if (!flags[Dirty::LogicOp]) { if (!flags[Dirty::LogicOp]) {
return; return;
} }
flags[Dirty::LogicOp] = false; flags[Dirty::LogicOp] = false;
const auto& regs = maxwell3d.regs; const auto& regs = maxwell3d->regs;
if (regs.logic_op.enable) { if (regs.logic_op.enable) {
glEnable(GL_COLOR_LOGIC_OP); glEnable(GL_COLOR_LOGIC_OP);
glLogicOp(MaxwellToGL::LogicOp(regs.logic_op.operation)); glLogicOp(MaxwellToGL::LogicOp(regs.logic_op.operation));
@ -950,7 +949,7 @@ void RasterizerOpenGL::SyncLogicOpState() {
} }
void RasterizerOpenGL::SyncScissorTest() { void RasterizerOpenGL::SyncScissorTest() {
auto& flags = maxwell3d.dirty.flags; auto& flags = maxwell3d->dirty.flags;
if (!flags[Dirty::Scissors] && !flags[VideoCommon::Dirty::RescaleScissors]) { if (!flags[Dirty::Scissors] && !flags[VideoCommon::Dirty::RescaleScissors]) {
return; return;
} }
@ -959,7 +958,7 @@ void RasterizerOpenGL::SyncScissorTest() {
const bool force = flags[VideoCommon::Dirty::RescaleScissors]; const bool force = flags[VideoCommon::Dirty::RescaleScissors];
flags[VideoCommon::Dirty::RescaleScissors] = false; flags[VideoCommon::Dirty::RescaleScissors] = false;
const auto& regs = maxwell3d.regs; const auto& regs = maxwell3d->regs;
const auto& resolution = Settings::values.resolution_info; const auto& resolution = Settings::values.resolution_info;
const bool is_rescaling{texture_cache.IsRescaling()}; const bool is_rescaling{texture_cache.IsRescaling()};
@ -995,39 +994,39 @@ void RasterizerOpenGL::SyncScissorTest() {
} }
void RasterizerOpenGL::SyncPointState() { void RasterizerOpenGL::SyncPointState() {
auto& flags = maxwell3d.dirty.flags; auto& flags = maxwell3d->dirty.flags;
if (!flags[Dirty::PointSize]) { if (!flags[Dirty::PointSize]) {
return; return;
} }
flags[Dirty::PointSize] = false; flags[Dirty::PointSize] = false;
oglEnable(GL_POINT_SPRITE, maxwell3d.regs.point_sprite_enable); oglEnable(GL_POINT_SPRITE, maxwell3d->regs.point_sprite_enable);
oglEnable(GL_PROGRAM_POINT_SIZE, maxwell3d.regs.vp_point_size.enable); oglEnable(GL_PROGRAM_POINT_SIZE, maxwell3d->regs.vp_point_size.enable);
const bool is_rescaling{texture_cache.IsRescaling()}; const bool is_rescaling{texture_cache.IsRescaling()};
const float scale = is_rescaling ? Settings::values.resolution_info.up_factor : 1.0f; const float scale = is_rescaling ? Settings::values.resolution_info.up_factor : 1.0f;
glPointSize(std::max(1.0f, maxwell3d.regs.point_size * scale)); glPointSize(std::max(1.0f, maxwell3d->regs.point_size * scale));
} }
void RasterizerOpenGL::SyncLineState() { void RasterizerOpenGL::SyncLineState() {
auto& flags = maxwell3d.dirty.flags; auto& flags = maxwell3d->dirty.flags;
if (!flags[Dirty::LineWidth]) { if (!flags[Dirty::LineWidth]) {
return; return;
} }
flags[Dirty::LineWidth] = false; flags[Dirty::LineWidth] = false;
const auto& regs = maxwell3d.regs; const auto& regs = maxwell3d->regs;
oglEnable(GL_LINE_SMOOTH, regs.line_smooth_enable); oglEnable(GL_LINE_SMOOTH, regs.line_smooth_enable);
glLineWidth(regs.line_smooth_enable ? regs.line_width_smooth : regs.line_width_aliased); glLineWidth(regs.line_smooth_enable ? regs.line_width_smooth : regs.line_width_aliased);
} }
void RasterizerOpenGL::SyncPolygonOffset() { void RasterizerOpenGL::SyncPolygonOffset() {
auto& flags = maxwell3d.dirty.flags; auto& flags = maxwell3d->dirty.flags;
if (!flags[Dirty::PolygonOffset]) { if (!flags[Dirty::PolygonOffset]) {
return; return;
} }
flags[Dirty::PolygonOffset] = false; flags[Dirty::PolygonOffset] = false;
const auto& regs = maxwell3d.regs; const auto& regs = maxwell3d->regs;
oglEnable(GL_POLYGON_OFFSET_FILL, regs.polygon_offset_fill_enable); oglEnable(GL_POLYGON_OFFSET_FILL, regs.polygon_offset_fill_enable);
oglEnable(GL_POLYGON_OFFSET_LINE, regs.polygon_offset_line_enable); oglEnable(GL_POLYGON_OFFSET_LINE, regs.polygon_offset_line_enable);
oglEnable(GL_POLYGON_OFFSET_POINT, regs.polygon_offset_point_enable); oglEnable(GL_POLYGON_OFFSET_POINT, regs.polygon_offset_point_enable);
@ -1041,13 +1040,13 @@ void RasterizerOpenGL::SyncPolygonOffset() {
} }
void RasterizerOpenGL::SyncAlphaTest() { void RasterizerOpenGL::SyncAlphaTest() {
auto& flags = maxwell3d.dirty.flags; auto& flags = maxwell3d->dirty.flags;
if (!flags[Dirty::AlphaTest]) { if (!flags[Dirty::AlphaTest]) {
return; return;
} }
flags[Dirty::AlphaTest] = false; flags[Dirty::AlphaTest] = false;
const auto& regs = maxwell3d.regs; const auto& regs = maxwell3d->regs;
if (regs.alpha_test_enabled) { if (regs.alpha_test_enabled) {
glEnable(GL_ALPHA_TEST); glEnable(GL_ALPHA_TEST);
glAlphaFunc(MaxwellToGL::ComparisonOp(regs.alpha_test_func), regs.alpha_test_ref); glAlphaFunc(MaxwellToGL::ComparisonOp(regs.alpha_test_func), regs.alpha_test_ref);
@ -1057,17 +1056,17 @@ void RasterizerOpenGL::SyncAlphaTest() {
} }
void RasterizerOpenGL::SyncFramebufferSRGB() { void RasterizerOpenGL::SyncFramebufferSRGB() {
auto& flags = maxwell3d.dirty.flags; auto& flags = maxwell3d->dirty.flags;
if (!flags[Dirty::FramebufferSRGB]) { if (!flags[Dirty::FramebufferSRGB]) {
return; return;
} }
flags[Dirty::FramebufferSRGB] = false; flags[Dirty::FramebufferSRGB] = false;
oglEnable(GL_FRAMEBUFFER_SRGB, maxwell3d.regs.framebuffer_srgb); oglEnable(GL_FRAMEBUFFER_SRGB, maxwell3d->regs.framebuffer_srgb);
} }
void RasterizerOpenGL::BeginTransformFeedback(GraphicsPipeline* program, GLenum primitive_mode) { void RasterizerOpenGL::BeginTransformFeedback(GraphicsPipeline* program, GLenum primitive_mode) {
const auto& regs = maxwell3d.regs; const auto& regs = maxwell3d->regs;
if (regs.tfb_enabled == 0) { if (regs.tfb_enabled == 0) {
return; return;
} }
@ -1086,11 +1085,48 @@ void RasterizerOpenGL::BeginTransformFeedback(GraphicsPipeline* program, GLenum
} }
void RasterizerOpenGL::EndTransformFeedback() { void RasterizerOpenGL::EndTransformFeedback() {
if (maxwell3d.regs.tfb_enabled != 0) { if (maxwell3d->regs.tfb_enabled != 0) {
glEndTransformFeedback(); glEndTransformFeedback();
} }
} }
void RasterizerOpenGL::InitializeChannel(Tegra::Control::ChannelState& channel) {
CreateChannel(channel);
{
std::scoped_lock lock{buffer_cache.mutex, texture_cache.mutex};
texture_cache.CreateChannel(channel);
buffer_cache.CreateChannel(channel);
}
shader_cache.CreateChannel(channel);
query_cache.CreateChannel(channel);
state_tracker.SetupTables(channel);
}
void RasterizerOpenGL::BindChannel(Tegra::Control::ChannelState& channel) {
const s32 channel_id = channel.bind_id;
BindToChannel(channel_id);
{
std::scoped_lock lock{buffer_cache.mutex, texture_cache.mutex};
texture_cache.BindToChannel(channel_id);
buffer_cache.BindToChannel(channel_id);
}
shader_cache.BindToChannel(channel_id);
query_cache.BindToChannel(channel_id);
state_tracker.ChangeChannel(channel);
state_tracker.InvalidateState();
}
void RasterizerOpenGL::ReleaseChannel(s32 channel_id) {
EraseChannel(channel_id);
{
std::scoped_lock lock{buffer_cache.mutex, texture_cache.mutex};
texture_cache.EraseChannel(channel_id);
buffer_cache.EraseChannel(channel_id);
}
shader_cache.EraseChannel(channel_id);
query_cache.EraseChannel(channel_id);
}
AccelerateDMA::AccelerateDMA(BufferCache& buffer_cache_) : buffer_cache{buffer_cache_} {} AccelerateDMA::AccelerateDMA(BufferCache& buffer_cache_) : buffer_cache{buffer_cache_} {}
bool AccelerateDMA::BufferCopy(GPUVAddr src_address, GPUVAddr dest_address, u64 amount) { bool AccelerateDMA::BufferCopy(GPUVAddr src_address, GPUVAddr dest_address, u64 amount) {

View file

@ -12,6 +12,7 @@
#include <glad/glad.h> #include <glad/glad.h>
#include "common/common_types.h" #include "common/common_types.h"
#include "video_core/control/channel_state_cache.h"
#include "video_core/engines/maxwell_dma.h" #include "video_core/engines/maxwell_dma.h"
#include "video_core/rasterizer_accelerated.h" #include "video_core/rasterizer_accelerated.h"
#include "video_core/rasterizer_interface.h" #include "video_core/rasterizer_interface.h"
@ -58,7 +59,8 @@ private:
BufferCache& buffer_cache; BufferCache& buffer_cache;
}; };
class RasterizerOpenGL : public VideoCore::RasterizerAccelerated { class RasterizerOpenGL : public VideoCore::RasterizerAccelerated,
protected VideoCommon::ChannelSetupCaches<VideoCommon::ChannelInfo> {
public: public:
explicit RasterizerOpenGL(Core::Frontend::EmuWindow& emu_window_, Tegra::GPU& gpu_, explicit RasterizerOpenGL(Core::Frontend::EmuWindow& emu_window_, Tegra::GPU& gpu_,
Core::Memory::Memory& cpu_memory_, const Device& device_, Core::Memory::Memory& cpu_memory_, const Device& device_,
@ -107,6 +109,12 @@ public:
return num_queued_commands > 0; return num_queued_commands > 0;
} }
void InitializeChannel(Tegra::Control::ChannelState& channel) override;
void BindChannel(Tegra::Control::ChannelState& channel) override;
void ReleaseChannel(s32 channel_id) override;
private: private:
static constexpr size_t MAX_TEXTURES = 192; static constexpr size_t MAX_TEXTURES = 192;
static constexpr size_t MAX_IMAGES = 48; static constexpr size_t MAX_IMAGES = 48;
@ -191,9 +199,6 @@ private:
void EndTransformFeedback(); void EndTransformFeedback();
Tegra::GPU& gpu; Tegra::GPU& gpu;
Tegra::Engines::Maxwell3D& maxwell3d;
Tegra::Engines::KeplerCompute& kepler_compute;
Tegra::MemoryManager& gpu_memory;
const Device& device; const Device& device;
ScreenInfo& screen_info; ScreenInfo& screen_info;

View file

@ -7,8 +7,8 @@
#include "common/common_types.h" #include "common/common_types.h"
#include "core/core.h" #include "core/core.h"
#include "video_core/control/channel_state.h"
#include "video_core/engines/maxwell_3d.h" #include "video_core/engines/maxwell_3d.h"
#include "video_core/gpu.h"
#include "video_core/renderer_opengl/gl_state_tracker.h" #include "video_core/renderer_opengl/gl_state_tracker.h"
#define OFF(field_name) MAXWELL3D_REG_INDEX(field_name) #define OFF(field_name) MAXWELL3D_REG_INDEX(field_name)
@ -202,9 +202,8 @@ void SetupDirtyMisc(Tables& tables) {
} // Anonymous namespace } // Anonymous namespace
StateTracker::StateTracker(Tegra::GPU& gpu) : flags{gpu.Maxwell3D().dirty.flags} { void StateTracker::SetupTables(Tegra::Control::ChannelState& channel_state) {
auto& dirty = gpu.Maxwell3D().dirty; auto& tables{channel_state.maxwell_3d->dirty.tables};
auto& tables = dirty.tables;
SetupDirtyFlags(tables); SetupDirtyFlags(tables);
SetupDirtyColorMasks(tables); SetupDirtyColorMasks(tables);
SetupDirtyViewports(tables); SetupDirtyViewports(tables);
@ -230,4 +229,14 @@ StateTracker::StateTracker(Tegra::GPU& gpu) : flags{gpu.Maxwell3D().dirty.flags}
SetupDirtyMisc(tables); SetupDirtyMisc(tables);
} }
void StateTracker::ChangeChannel(Tegra::Control::ChannelState& channel_state) {
flags = &channel_state.maxwell_3d->dirty.flags;
}
void StateTracker::InvalidateState() {
flags->set();
}
StateTracker::StateTracker() : flags{} {}
} // namespace OpenGL } // namespace OpenGL

View file

@ -12,8 +12,10 @@
#include "video_core/engines/maxwell_3d.h" #include "video_core/engines/maxwell_3d.h"
namespace Tegra { namespace Tegra {
class GPU; namespace Control {
struct ChannelState;
} }
} // namespace Tegra
namespace OpenGL { namespace OpenGL {
@ -83,7 +85,7 @@ static_assert(Last <= std::numeric_limits<u8>::max());
class StateTracker { class StateTracker {
public: public:
explicit StateTracker(Tegra::GPU& gpu); explicit StateTracker();
void BindIndexBuffer(GLuint new_index_buffer) { void BindIndexBuffer(GLuint new_index_buffer) {
if (index_buffer == new_index_buffer) { if (index_buffer == new_index_buffer) {
@ -121,94 +123,106 @@ public:
} }
void NotifyScreenDrawVertexArray() { void NotifyScreenDrawVertexArray() {
flags[OpenGL::Dirty::VertexFormats] = true; (*flags)[OpenGL::Dirty::VertexFormats] = true;
flags[OpenGL::Dirty::VertexFormat0 + 0] = true; (*flags)[OpenGL::Dirty::VertexFormat0 + 0] = true;
flags[OpenGL::Dirty::VertexFormat0 + 1] = true; (*flags)[OpenGL::Dirty::VertexFormat0 + 1] = true;
flags[VideoCommon::Dirty::VertexBuffers] = true; (*flags)[VideoCommon::Dirty::VertexBuffers] = true;
flags[VideoCommon::Dirty::VertexBuffer0] = true; (*flags)[VideoCommon::Dirty::VertexBuffer0] = true;
flags[OpenGL::Dirty::VertexInstances] = true; (*flags)[OpenGL::Dirty::VertexInstances] = true;
flags[OpenGL::Dirty::VertexInstance0 + 0] = true; (*flags)[OpenGL::Dirty::VertexInstance0 + 0] = true;
flags[OpenGL::Dirty::VertexInstance0 + 1] = true; (*flags)[OpenGL::Dirty::VertexInstance0 + 1] = true;
} }
void NotifyPolygonModes() { void NotifyPolygonModes() {
flags[OpenGL::Dirty::PolygonModes] = true; (*flags)[OpenGL::Dirty::PolygonModes] = true;
flags[OpenGL::Dirty::PolygonModeFront] = true; (*flags)[OpenGL::Dirty::PolygonModeFront] = true;
flags[OpenGL::Dirty::PolygonModeBack] = true; (*flags)[OpenGL::Dirty::PolygonModeBack] = true;
} }
void NotifyViewport0() { void NotifyViewport0() {
flags[OpenGL::Dirty::Viewports] = true; (*flags)[OpenGL::Dirty::Viewports] = true;
flags[OpenGL::Dirty::Viewport0] = true; (*flags)[OpenGL::Dirty::Viewport0] = true;
} }
void NotifyScissor0() { void NotifyScissor0() {
flags[OpenGL::Dirty::Scissors] = true; (*flags)[OpenGL::Dirty::Scissors] = true;
flags[OpenGL::Dirty::Scissor0] = true; (*flags)[OpenGL::Dirty::Scissor0] = true;
} }
void NotifyColorMask(size_t index) { void NotifyColorMask(size_t index) {
flags[OpenGL::Dirty::ColorMasks] = true; (*flags)[OpenGL::Dirty::ColorMasks] = true;
flags[OpenGL::Dirty::ColorMask0 + index] = true; (*flags)[OpenGL::Dirty::ColorMask0 + index] = true;
} }
void NotifyBlend0() { void NotifyBlend0() {
flags[OpenGL::Dirty::BlendStates] = true; (*flags)[OpenGL::Dirty::BlendStates] = true;
flags[OpenGL::Dirty::BlendState0] = true; (*flags)[OpenGL::Dirty::BlendState0] = true;
} }
void NotifyFramebuffer() { void NotifyFramebuffer() {
flags[VideoCommon::Dirty::RenderTargets] = true; (*flags)[VideoCommon::Dirty::RenderTargets] = true;
} }
void NotifyFrontFace() { void NotifyFrontFace() {
flags[OpenGL::Dirty::FrontFace] = true; (*flags)[OpenGL::Dirty::FrontFace] = true;
} }
void NotifyCullTest() { void NotifyCullTest() {
flags[OpenGL::Dirty::CullTest] = true; (*flags)[OpenGL::Dirty::CullTest] = true;
} }
void NotifyDepthMask() { void NotifyDepthMask() {
flags[OpenGL::Dirty::DepthMask] = true; (*flags)[OpenGL::Dirty::DepthMask] = true;
} }
void NotifyDepthTest() { void NotifyDepthTest() {
flags[OpenGL::Dirty::DepthTest] = true; (*flags)[OpenGL::Dirty::DepthTest] = true;
} }
void NotifyStencilTest() { void NotifyStencilTest() {
flags[OpenGL::Dirty::StencilTest] = true; (*flags)[OpenGL::Dirty::StencilTest] = true;
} }
void NotifyPolygonOffset() { void NotifyPolygonOffset() {
flags[OpenGL::Dirty::PolygonOffset] = true; (*flags)[OpenGL::Dirty::PolygonOffset] = true;
} }
void NotifyRasterizeEnable() { void NotifyRasterizeEnable() {
flags[OpenGL::Dirty::RasterizeEnable] = true; (*flags)[OpenGL::Dirty::RasterizeEnable] = true;
} }
void NotifyFramebufferSRGB() { void NotifyFramebufferSRGB() {
flags[OpenGL::Dirty::FramebufferSRGB] = true; (*flags)[OpenGL::Dirty::FramebufferSRGB] = true;
} }
void NotifyLogicOp() { void NotifyLogicOp() {
flags[OpenGL::Dirty::LogicOp] = true; (*flags)[OpenGL::Dirty::LogicOp] = true;
} }
void NotifyClipControl() { void NotifyClipControl() {
flags[OpenGL::Dirty::ClipControl] = true; (*flags)[OpenGL::Dirty::ClipControl] = true;
} }
void NotifyAlphaTest() { void NotifyAlphaTest() {
flags[OpenGL::Dirty::AlphaTest] = true; (*flags)[OpenGL::Dirty::AlphaTest] = true;
} }
void NotifyRange(u8 start, u8 end) {
for (auto flag = start; flag <= end; flag++) {
(*flags)[flag] = true;
}
}
void SetupTables(Tegra::Control::ChannelState& channel_state);
void ChangeChannel(Tegra::Control::ChannelState& channel_state);
void InvalidateState();
private: private:
Tegra::Engines::Maxwell3D::DirtyState::Flags& flags; Tegra::Engines::Maxwell3D::DirtyState::Flags* flags;
GLuint framebuffer = 0; GLuint framebuffer = 0;
GLuint index_buffer = 0; GLuint index_buffer = 0;

View file

@ -131,7 +131,7 @@ RendererOpenGL::RendererOpenGL(Core::TelemetrySession& telemetry_session_,
Core::Memory::Memory& cpu_memory_, Tegra::GPU& gpu_, Core::Memory::Memory& cpu_memory_, Tegra::GPU& gpu_,
std::unique_ptr<Core::Frontend::GraphicsContext> context_) std::unique_ptr<Core::Frontend::GraphicsContext> context_)
: RendererBase{emu_window_, std::move(context_)}, telemetry_session{telemetry_session_}, : RendererBase{emu_window_, std::move(context_)}, telemetry_session{telemetry_session_},
emu_window{emu_window_}, cpu_memory{cpu_memory_}, gpu{gpu_}, state_tracker{gpu}, emu_window{emu_window_}, cpu_memory{cpu_memory_}, gpu{gpu_}, state_tracker{},
program_manager{device}, program_manager{device},
rasterizer(emu_window, gpu, cpu_memory, device, screen_info, program_manager, state_tracker) { rasterizer(emu_window, gpu, cpu_memory, device, screen_info, program_manager, state_tracker) {
if (Settings::values.renderer_debug && GLAD_GL_KHR_debug) { if (Settings::values.renderer_debug && GLAD_GL_KHR_debug) {

View file

@ -106,7 +106,7 @@ RendererVulkan::RendererVulkan(Core::TelemetrySession& telemetry_session_,
surface(CreateSurface(instance, render_window)), surface(CreateSurface(instance, render_window)),
device(CreateDevice(instance, dld, *surface)), device(CreateDevice(instance, dld, *surface)),
memory_allocator(device, false), memory_allocator(device, false),
state_tracker(gpu), state_tracker(),
scheduler(device, state_tracker), scheduler(device, state_tracker),
swapchain(*surface, device, scheduler, render_window.GetFramebufferLayout().width, swapchain(*surface, device, scheduler, render_window.GetFramebufferLayout().width,
render_window.GetFramebufferLayout().height, false), render_window.GetFramebufferLayout().height, false),

View file

@ -995,7 +995,7 @@ void RasterizerVulkan::BindChannel(Tegra::Control::ChannelState& channel) {
pipeline_cache.BindToChannel(channel_id); pipeline_cache.BindToChannel(channel_id);
query_cache.BindToChannel(channel_id); query_cache.BindToChannel(channel_id);
state_tracker.ChangeChannel(channel); state_tracker.ChangeChannel(channel);
scheduler.InvalidateState(); state_tracker.InvalidateState();
} }
void RasterizerVulkan::ReleaseChannel(s32 channel_id) { void RasterizerVulkan::ReleaseChannel(s32 channel_id) {

View file

@ -10,7 +10,6 @@
#include "video_core/control/channel_state.h" #include "video_core/control/channel_state.h"
#include "video_core/dirty_flags.h" #include "video_core/dirty_flags.h"
#include "video_core/engines/maxwell_3d.h" #include "video_core/engines/maxwell_3d.h"
#include "video_core/gpu.h"
#include "video_core/renderer_vulkan/vk_state_tracker.h" #include "video_core/renderer_vulkan/vk_state_tracker.h"
#define OFF(field_name) MAXWELL3D_REG_INDEX(field_name) #define OFF(field_name) MAXWELL3D_REG_INDEX(field_name)
@ -203,7 +202,10 @@ void StateTracker::ChangeChannel(Tegra::Control::ChannelState& channel_state) {
flags = &channel_state.maxwell_3d->dirty.flags; flags = &channel_state.maxwell_3d->dirty.flags;
} }
StateTracker::StateTracker(Tegra::GPU& gpu) void StateTracker::InvalidateState() {
: flags{}, invalidation_flags{MakeInvalidationFlags()} {} flags->set();
}
StateTracker::StateTracker() : flags{}, invalidation_flags{MakeInvalidationFlags()} {}
} // namespace Vulkan } // namespace Vulkan

View file

@ -59,7 +59,7 @@ class StateTracker {
using Maxwell = Tegra::Engines::Maxwell3D::Regs; using Maxwell = Tegra::Engines::Maxwell3D::Regs;
public: public:
explicit StateTracker(Tegra::GPU& gpu); explicit StateTracker();
void InvalidateCommandBufferState() { void InvalidateCommandBufferState() {
(*flags) |= invalidation_flags; (*flags) |= invalidation_flags;
@ -149,6 +149,8 @@ public:
void ChangeChannel(Tegra::Control::ChannelState& channel_state); void ChangeChannel(Tegra::Control::ChannelState& channel_state);
void InvalidateState();
private: private:
static constexpr auto INVALID_TOPOLOGY = static_cast<Maxwell::PrimitiveTopology>(~0u); static constexpr auto INVALID_TOPOLOGY = static_cast<Maxwell::PrimitiveTopology>(~0u);