summaryrefslogtreecommitdiffstats
path: root/src/video_core/renderer_opengl
diff options
context:
space:
mode:
authorZach Hilman <DarkLordZach@users.noreply.github.com>2019-06-07 23:23:25 +0200
committerGitHub <noreply@github.com>2019-06-07 23:23:25 +0200
commitde33ad25f52960449a97caa2b25e37e6a35f0710 (patch)
tree5f70bb84aafac68b6c34c95fec033528bff26d4e /src/video_core/renderer_opengl
parentMerge pull request #2558 from ReinUsesLisp/shader-nodes (diff)
parentgl_buffer_cache: Remove unused ReserveMemory method (diff)
downloadyuzu-de33ad25f52960449a97caa2b25e37e6a35f0710.tar
yuzu-de33ad25f52960449a97caa2b25e37e6a35f0710.tar.gz
yuzu-de33ad25f52960449a97caa2b25e37e6a35f0710.tar.bz2
yuzu-de33ad25f52960449a97caa2b25e37e6a35f0710.tar.lz
yuzu-de33ad25f52960449a97caa2b25e37e6a35f0710.tar.xz
yuzu-de33ad25f52960449a97caa2b25e37e6a35f0710.tar.zst
yuzu-de33ad25f52960449a97caa2b25e37e6a35f0710.zip
Diffstat (limited to 'src/video_core/renderer_opengl')
-rw-r--r--src/video_core/renderer_opengl/gl_buffer_cache.cpp10
-rw-r--r--src/video_core/renderer_opengl/gl_buffer_cache.h3
-rw-r--r--src/video_core/renderer_opengl/gl_primitive_assembler.cpp63
-rw-r--r--src/video_core/renderer_opengl/gl_primitive_assembler.h31
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp51
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.h6
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp20
-rw-r--r--src/video_core/renderer_opengl/gl_shader_gen.cpp27
-rw-r--r--src/video_core/renderer_opengl/gl_shader_manager.cpp11
-rw-r--r--src/video_core/renderer_opengl/gl_shader_manager.h8
-rw-r--r--src/video_core/renderer_opengl/gl_state.cpp13
-rw-r--r--src/video_core/renderer_opengl/gl_state.h7
-rw-r--r--src/video_core/renderer_opengl/maxwell_to_gl.h9
13 files changed, 40 insertions, 219 deletions
diff --git a/src/video_core/renderer_opengl/gl_buffer_cache.cpp b/src/video_core/renderer_opengl/gl_buffer_cache.cpp
index 25652e794..48b86f3bd 100644
--- a/src/video_core/renderer_opengl/gl_buffer_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_buffer_cache.cpp
@@ -71,16 +71,6 @@ GLintptr OGLBufferCache::UploadHostMemory(const void* raw_pointer, std::size_t s
return uploaded_offset;
}
-std::tuple<u8*, GLintptr> OGLBufferCache::ReserveMemory(std::size_t size, std::size_t alignment) {
- AlignBuffer(alignment);
- u8* const uploaded_ptr = buffer_ptr;
- const GLintptr uploaded_offset = buffer_offset;
-
- buffer_ptr += size;
- buffer_offset += size;
- return std::make_tuple(uploaded_ptr, uploaded_offset);
-}
-
bool OGLBufferCache::Map(std::size_t max_size) {
bool invalidate;
std::tie(buffer_ptr, buffer_offset_base, invalidate) =
diff --git a/src/video_core/renderer_opengl/gl_buffer_cache.h b/src/video_core/renderer_opengl/gl_buffer_cache.h
index f9247a40e..f2347581b 100644
--- a/src/video_core/renderer_opengl/gl_buffer_cache.h
+++ b/src/video_core/renderer_opengl/gl_buffer_cache.h
@@ -61,9 +61,6 @@ public:
/// Uploads from a host memory. Returns host's buffer offset where it's been allocated.
GLintptr UploadHostMemory(const void* raw_pointer, std::size_t size, std::size_t alignment = 4);
- /// Reserves memory to be used by host's CPU. Returns mapped address and offset.
- std::tuple<u8*, GLintptr> ReserveMemory(std::size_t size, std::size_t alignment = 4);
-
bool Map(std::size_t max_size);
void Unmap();
diff --git a/src/video_core/renderer_opengl/gl_primitive_assembler.cpp b/src/video_core/renderer_opengl/gl_primitive_assembler.cpp
deleted file mode 100644
index c3e94d917..000000000
--- a/src/video_core/renderer_opengl/gl_primitive_assembler.cpp
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright 2018 yuzu Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#include <algorithm>
-#include <array>
-#include "common/assert.h"
-#include "common/common_types.h"
-#include "core/core.h"
-#include "video_core/memory_manager.h"
-#include "video_core/renderer_opengl/gl_buffer_cache.h"
-#include "video_core/renderer_opengl/gl_primitive_assembler.h"
-
-namespace OpenGL {
-
-constexpr u32 TRIANGLES_PER_QUAD = 6;
-constexpr std::array<u32, TRIANGLES_PER_QUAD> QUAD_MAP = {0, 1, 2, 0, 2, 3};
-
-PrimitiveAssembler::PrimitiveAssembler(OGLBufferCache& buffer_cache) : buffer_cache(buffer_cache) {}
-
-PrimitiveAssembler::~PrimitiveAssembler() = default;
-
-std::size_t PrimitiveAssembler::CalculateQuadSize(u32 count) const {
- ASSERT_MSG(count % 4 == 0, "Quad count is expected to be a multiple of 4");
- return (count / 4) * TRIANGLES_PER_QUAD * sizeof(GLuint);
-}
-
-GLintptr PrimitiveAssembler::MakeQuadArray(u32 first, u32 count) {
- const std::size_t size{CalculateQuadSize(count)};
- auto [dst_pointer, index_offset] = buffer_cache.ReserveMemory(size);
-
- for (u32 primitive = 0; primitive < count / 4; ++primitive) {
- for (u32 i = 0; i < TRIANGLES_PER_QUAD; ++i) {
- const u32 index = first + primitive * 4 + QUAD_MAP[i];
- std::memcpy(dst_pointer, &index, sizeof(index));
- dst_pointer += sizeof(index);
- }
- }
-
- return index_offset;
-}
-
-GLintptr PrimitiveAssembler::MakeQuadIndexed(GPUVAddr gpu_addr, std::size_t index_size, u32 count) {
- const std::size_t map_size{CalculateQuadSize(count)};
- auto [dst_pointer, index_offset] = buffer_cache.ReserveMemory(map_size);
-
- auto& memory_manager = Core::System::GetInstance().GPU().MemoryManager();
- const u8* source{memory_manager.GetPointer(gpu_addr)};
-
- for (u32 primitive = 0; primitive < count / 4; ++primitive) {
- for (std::size_t i = 0; i < TRIANGLES_PER_QUAD; ++i) {
- const u32 index = primitive * 4 + QUAD_MAP[i];
- const u8* src_offset = source + (index * index_size);
-
- std::memcpy(dst_pointer, src_offset, index_size);
- dst_pointer += index_size;
- }
- }
-
- return index_offset;
-}
-
-} // namespace OpenGL
diff --git a/src/video_core/renderer_opengl/gl_primitive_assembler.h b/src/video_core/renderer_opengl/gl_primitive_assembler.h
deleted file mode 100644
index 4e87ce4d6..000000000
--- a/src/video_core/renderer_opengl/gl_primitive_assembler.h
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2018 yuzu Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#pragma once
-
-#include <glad/glad.h>
-
-#include "common/common_types.h"
-
-namespace OpenGL {
-
-class OGLBufferCache;
-
-class PrimitiveAssembler {
-public:
- explicit PrimitiveAssembler(OGLBufferCache& buffer_cache);
- ~PrimitiveAssembler();
-
- /// Calculates the size required by MakeQuadArray and MakeQuadIndexed.
- std::size_t CalculateQuadSize(u32 count) const;
-
- GLintptr MakeQuadArray(u32 first, u32 count);
-
- GLintptr MakeQuadIndexed(GPUVAddr gpu_addr, std::size_t index_size, u32 count);
-
-private:
- OGLBufferCache& buffer_cache;
-};
-
-} // namespace OpenGL \ No newline at end of file
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index f9b6dfeea..ca410287a 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -246,29 +246,6 @@ DrawParameters RasterizerOpenGL::SetupDraw() {
DrawParameters params{};
params.current_instance = gpu.state.current_instance;
- if (regs.draw.topology == Maxwell::PrimitiveTopology::Quads) {
- MICROPROFILE_SCOPE(OpenGL_PrimitiveAssembly);
-
- params.use_indexed = true;
- params.primitive_mode = GL_TRIANGLES;
-
- if (is_indexed) {
- params.index_format = MaxwellToGL::IndexFormat(regs.index_array.format);
- params.count = (regs.index_array.count / 4) * 6;
- params.index_buffer_offset = primitive_assembler.MakeQuadIndexed(
- regs.index_array.IndexStart(), regs.index_array.FormatSizeInBytes(),
- regs.index_array.count);
- params.base_vertex = static_cast<GLint>(regs.vb_element_base);
- } else {
- // MakeQuadArray always generates u32 indexes
- params.index_format = GL_UNSIGNED_INT;
- params.count = (regs.vertex_buffer.count / 4) * 6;
- params.index_buffer_offset = primitive_assembler.MakeQuadArray(
- regs.vertex_buffer.first, regs.vertex_buffer.count);
- }
- return params;
- }
-
params.use_indexed = is_indexed;
params.primitive_mode = MaxwellToGL::PrimitiveTopology(regs.draw.topology);
@@ -686,30 +663,19 @@ void RasterizerOpenGL::DrawArrays() {
SyncCullMode();
SyncPrimitiveRestart();
SyncScissorTest(state);
- // Alpha Testing is synced on shaders.
SyncTransformFeedback();
SyncPointState();
- CheckAlphaTests();
SyncPolygonOffset();
- // TODO(bunnei): Sync framebuffer_scale uniform here
- // TODO(bunnei): Sync scissorbox uniform(s) here
+ SyncAlphaTest();
// Draw the vertex batch
const bool is_indexed = accelerate_draw == AccelDraw::Indexed;
std::size_t buffer_size = CalculateVertexArraysSize();
- // Add space for index buffer (keeping in mind non-core primitives)
- switch (regs.draw.topology) {
- case Maxwell::PrimitiveTopology::Quads:
- buffer_size = Common::AlignUp(buffer_size, 4) +
- primitive_assembler.CalculateQuadSize(regs.vertex_buffer.count);
- break;
- default:
- if (is_indexed) {
- buffer_size = Common::AlignUp(buffer_size, 4) + CalculateIndexBufferSize();
- }
- break;
+ // Add space for index buffer
+ if (is_indexed) {
+ buffer_size = Common::AlignUp(buffer_size, 4) + CalculateIndexBufferSize();
}
// Uniform space for the 5 shader stages
@@ -1152,10 +1118,17 @@ void RasterizerOpenGL::SyncPolygonOffset() {
state.polygon_offset.clamp = regs.polygon_offset_clamp;
}
-void RasterizerOpenGL::CheckAlphaTests() {
+void RasterizerOpenGL::SyncAlphaTest() {
const auto& regs = system.GPU().Maxwell3D().regs;
UNIMPLEMENTED_IF_MSG(regs.alpha_test_enabled != 0 && regs.rt_control.count > 1,
"Alpha Testing is enabled with more than one rendertarget");
+
+ state.alpha_test.enabled = regs.alpha_test_enabled;
+ if (!state.alpha_test.enabled) {
+ return;
+ }
+ state.alpha_test.func = MaxwellToGL::ComparisonOp(regs.alpha_test_func);
+ state.alpha_test.ref = regs.alpha_test_ref;
}
} // namespace OpenGL
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h
index d78094138..2817f65c9 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer.h
@@ -23,7 +23,6 @@
#include "video_core/renderer_opengl/gl_buffer_cache.h"
#include "video_core/renderer_opengl/gl_device.h"
#include "video_core/renderer_opengl/gl_global_cache.h"
-#include "video_core/renderer_opengl/gl_primitive_assembler.h"
#include "video_core/renderer_opengl/gl_rasterizer_cache.h"
#include "video_core/renderer_opengl/gl_resource_manager.h"
#include "video_core/renderer_opengl/gl_sampler_cache.h"
@@ -167,8 +166,8 @@ private:
/// Syncs the polygon offsets
void SyncPolygonOffset();
- /// Check asserts for alpha testing.
- void CheckAlphaTests();
+ /// Syncs the alpha test state to match the guest state
+ void SyncAlphaTest();
/// Check for extension that are not strictly required
/// but are needed for correct emulation
@@ -197,7 +196,6 @@ private:
static constexpr std::size_t STREAM_BUFFER_SIZE = 128 * 1024 * 1024;
OGLBufferCache buffer_cache;
- PrimitiveAssembler primitive_assembler{buffer_cache};
BindBuffersRangePushBuffer bind_ubo_pushbuffer{GL_UNIFORM_BUFFER};
BindBuffersRangePushBuffer bind_ssbo_pushbuffer{GL_SHADER_STORAGE_BUFFER};
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index f2d0722af..739477cc9 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -1467,27 +1467,9 @@ private:
UNIMPLEMENTED_IF_MSG(header.ps.omap.sample_mask != 0, "Sample mask write is unimplemented");
- code.AddLine("if (alpha_test[0] != 0) {{");
- ++code.scope;
- // We start on the register containing the alpha value in the first RT.
- u32 current_reg = 3;
- for (u32 render_target = 0; render_target < Maxwell::NumRenderTargets; ++render_target) {
- // TODO(Blinkhawk): verify the behavior of alpha testing on hardware when
- // multiple render targets are used.
- if (header.ps.IsColorComponentOutputEnabled(render_target, 0) ||
- header.ps.IsColorComponentOutputEnabled(render_target, 1) ||
- header.ps.IsColorComponentOutputEnabled(render_target, 2) ||
- header.ps.IsColorComponentOutputEnabled(render_target, 3)) {
- code.AddLine("if (!AlphaFunc({})) discard;", SafeGetRegister(current_reg));
- current_reg += 4;
- }
- }
- --code.scope;
- code.AddLine("}}");
-
// Write the color outputs using the data in the shader registers, disabled
// rendertargets/components are skipped in the register assignment.
- current_reg = 0;
+ u32 current_reg = 0;
for (u32 render_target = 0; render_target < Maxwell::NumRenderTargets; ++render_target) {
// TODO(Subv): Figure out how dual-source blending is configured in the Switch.
for (u32 component = 0; component < 4; ++component) {
diff --git a/src/video_core/renderer_opengl/gl_shader_gen.cpp b/src/video_core/renderer_opengl/gl_shader_gen.cpp
index c845b29aa..9148629ec 100644
--- a/src/video_core/renderer_opengl/gl_shader_gen.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_gen.cpp
@@ -26,7 +26,6 @@ ProgramResult GenerateVertexShader(const Device& device, const ShaderSetup& setu
layout (std140, binding = EMULATION_UBO_BINDING) uniform vs_config {
vec4 viewport_flip;
uvec4 config_pack; // instance_id, flip_stage, y_direction, padding
- uvec4 alpha_test;
};
)";
@@ -78,7 +77,6 @@ ProgramResult GenerateGeometryShader(const Device& device, const ShaderSetup& se
layout (std140, binding = EMULATION_UBO_BINDING) uniform gs_config {
vec4 viewport_flip;
uvec4 config_pack; // instance_id, flip_stage, y_direction, padding
- uvec4 alpha_test;
};
)";
@@ -114,33 +112,8 @@ layout (location = 7) out vec4 FragColor7;
layout (std140, binding = EMULATION_UBO_BINDING) uniform fs_config {
vec4 viewport_flip;
uvec4 config_pack; // instance_id, flip_stage, y_direction, padding
- uvec4 alpha_test;
};
-bool AlphaFunc(in float value) {
- float ref = uintBitsToFloat(alpha_test[2]);
- switch (alpha_test[1]) {
- case 1:
- return false;
- case 2:
- return value < ref;
- case 3:
- return value == ref;
- case 4:
- return value <= ref;
- case 5:
- return value > ref;
- case 6:
- return value != ref;
- case 7:
- return value >= ref;
- case 8:
- return true;
- default:
- return false;
- }
-}
-
)";
const ShaderIR program_ir(setup.program.code, PROGRAM_OFFSET);
ProgramResult program =
diff --git a/src/video_core/renderer_opengl/gl_shader_manager.cpp b/src/video_core/renderer_opengl/gl_shader_manager.cpp
index 05ab01dcb..b05f90f20 100644
--- a/src/video_core/renderer_opengl/gl_shader_manager.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_manager.cpp
@@ -48,17 +48,6 @@ void MaxwellUniformData::SetFromRegs(const Maxwell3D& maxwell, std::size_t shade
viewport_flip[0] = regs.viewport_transform[0].scale_x < 0.0 ? -1.0f : 1.0f;
viewport_flip[1] = regs.viewport_transform[0].scale_y < 0.0 ? -1.0f : 1.0f;
- auto func{static_cast<u32>(regs.alpha_test_func)};
- // Normalize the gl variants of opCompare to be the same as the normal variants
- const u32 op_gl_variant_base = static_cast<u32>(Maxwell3D::Regs::ComparisonOp::Never);
- if (func >= op_gl_variant_base) {
- func = func - op_gl_variant_base + 1U;
- }
-
- alpha_test.enabled = regs.alpha_test_enabled;
- alpha_test.func = func;
- alpha_test.ref = regs.alpha_test_ref;
-
instance_id = state.current_instance;
// Assign in which stage the position has to be flipped
diff --git a/src/video_core/renderer_opengl/gl_shader_manager.h b/src/video_core/renderer_opengl/gl_shader_manager.h
index cec18a832..6961e702a 100644
--- a/src/video_core/renderer_opengl/gl_shader_manager.h
+++ b/src/video_core/renderer_opengl/gl_shader_manager.h
@@ -27,14 +27,8 @@ struct MaxwellUniformData {
GLuint flip_stage;
GLfloat y_direction;
};
- struct alignas(16) {
- GLuint enabled;
- GLuint func;
- GLfloat ref;
- GLuint padding;
- } alpha_test;
};
-static_assert(sizeof(MaxwellUniformData) == 48, "MaxwellUniformData structure size is incorrect");
+static_assert(sizeof(MaxwellUniformData) == 32, "MaxwellUniformData structure size is incorrect");
static_assert(sizeof(MaxwellUniformData) < 16384,
"MaxwellUniformData structure must be less than 16kb as per the OpenGL spec");
diff --git a/src/video_core/renderer_opengl/gl_state.cpp b/src/video_core/renderer_opengl/gl_state.cpp
index 7425fbe5d..d86e137ac 100644
--- a/src/video_core/renderer_opengl/gl_state.cpp
+++ b/src/video_core/renderer_opengl/gl_state.cpp
@@ -156,6 +156,10 @@ OpenGLState::OpenGLState() {
polygon_offset.factor = 0.0f;
polygon_offset.units = 0.0f;
polygon_offset.clamp = 0.0f;
+
+ alpha_test.enabled = false;
+ alpha_test.func = GL_ALWAYS;
+ alpha_test.ref = 0.0f;
}
void OpenGLState::ApplyDefaultState() {
@@ -461,6 +465,14 @@ void OpenGLState::ApplyPolygonOffset() const {
}
}
+void OpenGLState::ApplyAlphaTest() const {
+ Enable(GL_ALPHA_TEST, cur_state.alpha_test.enabled, alpha_test.enabled);
+ if (UpdateTie(std::tie(cur_state.alpha_test.func, cur_state.alpha_test.ref),
+ std::tie(alpha_test.func, alpha_test.ref))) {
+ glAlphaFunc(alpha_test.func, alpha_test.ref);
+ }
+}
+
void OpenGLState::ApplyTextures() const {
bool has_delta{};
std::size_t first{};
@@ -533,6 +545,7 @@ void OpenGLState::Apply() const {
ApplyTextures();
ApplySamplers();
ApplyPolygonOffset();
+ ApplyAlphaTest();
}
void OpenGLState::EmulateViewportWithScissor() {
diff --git a/src/video_core/renderer_opengl/gl_state.h b/src/video_core/renderer_opengl/gl_state.h
index 41418a7b8..b0140495d 100644
--- a/src/video_core/renderer_opengl/gl_state.h
+++ b/src/video_core/renderer_opengl/gl_state.h
@@ -172,6 +172,12 @@ public:
GLfloat clamp;
} polygon_offset;
+ struct {
+ bool enabled; // GL_ALPHA_TEST
+ GLenum func; // GL_ALPHA_TEST_FUNC
+ GLfloat ref; // GL_ALPHA_TEST_REF
+ } alpha_test;
+
std::array<bool, 8> clip_distance; // GL_CLIP_DISTANCE
OpenGLState();
@@ -215,6 +221,7 @@ public:
void ApplySamplers() const;
void ApplyDepthClamp() const;
void ApplyPolygonOffset() const;
+ void ApplyAlphaTest() const;
/// Set the initial OpenGL state
static void ApplyDefaultState();
diff --git a/src/video_core/renderer_opengl/maxwell_to_gl.h b/src/video_core/renderer_opengl/maxwell_to_gl.h
index ed7b5cff0..ea77dd211 100644
--- a/src/video_core/renderer_opengl/maxwell_to_gl.h
+++ b/src/video_core/renderer_opengl/maxwell_to_gl.h
@@ -128,6 +128,8 @@ inline GLenum PrimitiveTopology(Maxwell::PrimitiveTopology topology) {
return GL_TRIANGLE_STRIP;
case Maxwell::PrimitiveTopology::TriangleFan:
return GL_TRIANGLE_FAN;
+ case Maxwell::PrimitiveTopology::Quads:
+ return GL_QUADS;
default:
LOG_CRITICAL(Render_OpenGL, "Unimplemented topology={}", static_cast<u32>(topology));
UNREACHABLE();
@@ -173,11 +175,8 @@ inline GLenum WrapMode(Tegra::Texture::WrapMode wrap_mode) {
return GL_CLAMP_TO_EDGE;
case Tegra::Texture::WrapMode::Border:
return GL_CLAMP_TO_BORDER;
- case Tegra::Texture::WrapMode::ClampOGL:
- // TODO(Subv): GL_CLAMP was removed as of OpenGL 3.1, to implement GL_CLAMP, we can use
- // GL_CLAMP_TO_BORDER to get the border color of the texture, and then sample the edge to
- // manually mix them. However the shader part of this is not yet implemented.
- return GL_CLAMP_TO_BORDER;
+ case Tegra::Texture::WrapMode::Clamp:
+ return GL_CLAMP;
case Tegra::Texture::WrapMode::MirrorOnceClampToEdge:
return GL_MIRROR_CLAMP_TO_EDGE;
case Tegra::Texture::WrapMode::MirrorOnceBorder: