aboutsummaryrefslogtreecommitdiff
path: root/src/video_core
diff options
context:
space:
mode:
Diffstat (limited to 'src/video_core')
-rw-r--r--src/video_core/clipper.cpp6
-rw-r--r--src/video_core/command_processor.cpp30
-rw-r--r--src/video_core/debug_utils/debug_utils.cpp138
-rw-r--r--src/video_core/debug_utils/debug_utils.h148
-rw-r--r--src/video_core/gpu_debugger.h2
-rw-r--r--src/video_core/pica.h42
-rw-r--r--src/video_core/primitive_assembly.cpp2
-rw-r--r--src/video_core/rasterizer.cpp12
-rw-r--r--src/video_core/renderer_base.h2
-rw-r--r--src/video_core/renderer_opengl/gl_shader_util.cpp34
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.cpp45
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.h11
-rw-r--r--src/video_core/utils.cpp4
-rw-r--r--src/video_core/utils.h20
-rw-r--r--src/video_core/vertex_shader.cpp22
-rw-r--r--src/video_core/vertex_shader.h2
-rw-r--r--src/video_core/video_core.cpp8
17 files changed, 417 insertions, 111 deletions
diff --git a/src/video_core/clipper.cpp b/src/video_core/clipper.cpp
index 96d3dabe2..632fb959a 100644
--- a/src/video_core/clipper.cpp
+++ b/src/video_core/clipper.cpp
@@ -157,12 +157,12 @@ void ProcessTriangle(OutputVertex &v0, OutputVertex &v1, OutputVertex &v2) {
InitScreenCoordinates(vtx2);
- DEBUG_LOG(GPU,
+ LOG_TRACE(Render_Software,
"Triangle %lu/%lu (%lu buffer vertices) at position (%.3f, %.3f, %.3f, %.3f), "
- "(%.3lu, %.3f, %.3f, %.3f), (%.3f, %.3f, %.3f, %.3f) and "
+ "(%.3f, %.3f, %.3f, %.3f), (%.3f, %.3f, %.3f, %.3f) and "
"screen position (%.2f, %.2f, %.2f), (%.2f, %.2f, %.2f), (%.2f, %.2f, %.2f)",
i,output_list.size(), buffer_vertices.size(),
- vtx0.pos.x.ToFloat32(), vtx0.pos.y.ToFloat32(), vtx0.pos.z.ToFloat32(), vtx0.pos.w.ToFloat32(),output_list.size(),
+ vtx0.pos.x.ToFloat32(), vtx0.pos.y.ToFloat32(), vtx0.pos.z.ToFloat32(), vtx0.pos.w.ToFloat32(),
vtx1.pos.x.ToFloat32(), vtx1.pos.y.ToFloat32(), vtx1.pos.z.ToFloat32(), vtx1.pos.w.ToFloat32(),
vtx2.pos.x.ToFloat32(), vtx2.pos.y.ToFloat32(), vtx2.pos.z.ToFloat32(), vtx2.pos.w.ToFloat32(),
vtx0.screenpos.x.ToFloat32(), vtx0.screenpos.y.ToFloat32(), vtx0.screenpos.z.ToFloat32(),
diff --git a/src/video_core/command_processor.cpp b/src/video_core/command_processor.cpp
index 1ec727698..b74cd3261 100644
--- a/src/video_core/command_processor.cpp
+++ b/src/video_core/command_processor.cpp
@@ -8,6 +8,7 @@
#include "pica.h"
#include "primitive_assembly.h"
#include "vertex_shader.h"
+#include "core/hle/service/gsp_gpu.h"
#include "debug_utils/debug_utils.h"
@@ -34,15 +35,26 @@ static inline void WritePicaReg(u32 id, u32 value, u32 mask) {
u32 old_value = registers[id];
registers[id] = (old_value & ~mask) | (value & mask);
+ if (g_debug_context)
+ g_debug_context->OnEvent(DebugContext::Event::CommandLoaded, reinterpret_cast<void*>(&id));
+
DebugUtils::OnPicaRegWrite(id, registers[id]);
switch(id) {
+ // Trigger IRQ
+ case PICA_REG_INDEX(trigger_irq):
+ GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::P3D);
+ return;
+
// It seems like these trigger vertex rendering
case PICA_REG_INDEX(trigger_draw):
case PICA_REG_INDEX(trigger_draw_indexed):
{
DebugUtils::DumpTevStageConfig(registers.GetTevStages());
+ if (g_debug_context)
+ g_debug_context->OnEvent(DebugContext::Event::IncomingPrimitiveBatch, nullptr);
+
const auto& attribute_config = registers.vertex_attributes;
const u8* const base_address = Memory::GetPointer(attribute_config.GetBaseAddress());
@@ -60,7 +72,7 @@ static inline void WritePicaReg(u32 id, u32 value, u32 mask) {
const u8* load_address = base_address + loader_config.data_offset;
// TODO: What happens if a loader overwrites a previous one's data?
- for (int component = 0; component < loader_config.component_count; ++component) {
+ for (unsigned component = 0; component < loader_config.component_count; ++component) {
u32 attribute_index = loader_config.GetComponent(component);
vertex_attribute_sources[attribute_index] = load_address;
vertex_attribute_strides[attribute_index] = static_cast<u32>(loader_config.byte_count);
@@ -102,7 +114,7 @@ static inline void WritePicaReg(u32 id, u32 value, u32 mask) {
(vertex_attribute_formats[i] == 2) ? *(s16*)srcdata :
*(float*)srcdata;
input.attr[i][comp] = float24::FromFloat32(srcval);
- DEBUG_LOG(GPU, "Loaded component %x of attribute %x for vertex %x (index %x) from 0x%08x + 0x%08lx + 0x%04lx: %f",
+ LOG_TRACE(HW_GPU, "Loaded component %x of attribute %x for vertex %x (index %x) from 0x%08x + 0x%08lx + 0x%04lx: %f",
comp, i, vertex, index,
attribute_config.GetBaseAddress(),
vertex_attribute_sources[i] - base_address,
@@ -132,6 +144,10 @@ static inline void WritePicaReg(u32 id, u32 value, u32 mask) {
clipper_primitive_assembler.SubmitVertex(output, Clipper::ProcessTriangle);
}
geometry_dumper.Dump();
+
+ if (g_debug_context)
+ g_debug_context->OnEvent(DebugContext::Event::FinishedPrimitiveBatch, nullptr);
+
break;
}
@@ -160,7 +176,7 @@ static inline void WritePicaReg(u32 id, u32 value, u32 mask) {
auto& uniform = VertexShader::GetFloatUniform(uniform_setup.index);
if (uniform_setup.index > 95) {
- ERROR_LOG(GPU, "Invalid VS uniform index %d", (int)uniform_setup.index);
+ LOG_ERROR(HW_GPU, "Invalid VS uniform index %d", (int)uniform_setup.index);
break;
}
@@ -176,7 +192,7 @@ static inline void WritePicaReg(u32 id, u32 value, u32 mask) {
uniform.x = float24::FromRawFloat24(uniform_write_buffer[2] & 0xFFFFFF);
}
- DEBUG_LOG(GPU, "Set uniform %x to (%f %f %f %f)", (int)uniform_setup.index,
+ LOG_TRACE(HW_GPU, "Set uniform %x to (%f %f %f %f)", (int)uniform_setup.index,
uniform.x.ToFloat32(), uniform.y.ToFloat32(), uniform.z.ToFloat32(),
uniform.w.ToFloat32());
@@ -229,6 +245,9 @@ static inline void WritePicaReg(u32 id, u32 value, u32 mask) {
default:
break;
}
+
+ if (g_debug_context)
+ g_debug_context->OnEvent(DebugContext::Event::CommandProcessed, reinterpret_cast<void*>(&id));
}
static std::ptrdiff_t ExecuteCommandBlock(const u32* first_command_word) {
@@ -259,8 +278,9 @@ static std::ptrdiff_t ExecuteCommandBlock(const u32* first_command_word) {
void ProcessCommandList(const u32* list, u32 size) {
u32* read_pointer = (u32*)list;
+ u32 list_length = size / sizeof(u32);
- while (read_pointer < list + size) {
+ while (read_pointer < list + list_length) {
read_pointer += ExecuteCommandBlock(read_pointer);
}
}
diff --git a/src/video_core/debug_utils/debug_utils.cpp b/src/video_core/debug_utils/debug_utils.cpp
index 22b8e9950..1a20f19ec 100644
--- a/src/video_core/debug_utils/debug_utils.cpp
+++ b/src/video_core/debug_utils/debug_utils.cpp
@@ -3,6 +3,8 @@
// Refer to the license.txt file included.
#include <algorithm>
+#include <condition_variable>
+#include <list>
#include <map>
#include <fstream>
#include <mutex>
@@ -12,14 +14,56 @@
#include <png.h>
#endif
+#include "common/log.h"
#include "common/file_util.h"
+#include "video_core/math.h"
#include "video_core/pica.h"
#include "debug_utils.h"
namespace Pica {
+void DebugContext::OnEvent(Event event, void* data) {
+ if (!breakpoints[event].enabled)
+ return;
+
+ {
+ std::unique_lock<std::mutex> lock(breakpoint_mutex);
+
+ // TODO: Should stop the CPU thread here once we multithread emulation.
+
+ active_breakpoint = event;
+ at_breakpoint = true;
+
+ // Tell all observers that we hit a breakpoint
+ for (auto& breakpoint_observer : breakpoint_observers) {
+ breakpoint_observer->OnPicaBreakPointHit(event, data);
+ }
+
+ // Wait until another thread tells us to Resume()
+ resume_from_breakpoint.wait(lock, [&]{ return !at_breakpoint; });
+ }
+}
+
+void DebugContext::Resume() {
+ {
+ std::unique_lock<std::mutex> lock(breakpoint_mutex);
+
+ // Tell all observers that we are about to resume
+ for (auto& breakpoint_observer : breakpoint_observers) {
+ breakpoint_observer->OnPicaResume();
+ }
+
+ // Resume the waiting thread (i.e. OnEvent())
+ at_breakpoint = false;
+ }
+
+ resume_from_breakpoint.notify_one();
+}
+
+std::shared_ptr<DebugContext> g_debug_context; // TODO: Get rid of this global
+
namespace DebugUtils {
void GeometryDumper::AddTriangle(Vertex& v0, Vertex& v1, Vertex& v2) {
@@ -155,7 +199,7 @@ void DumpShader(const u32* binary_data, u32 binary_size, const u32* swizzle_data
// This is put into a try-catch block to make sure we notice unknown configurations.
std::vector<OutputRegisterInfo> output_info_table;
- for (int i = 0; i < 7; ++i) {
+ for (unsigned i = 0; i < 7; ++i) {
using OutputAttributes = Pica::Regs::VSOutputAttributes;
// TODO: It's still unclear how the attribute components map to the register!
@@ -204,8 +248,8 @@ void DumpShader(const u32* binary_data, u32 binary_size, const u32* swizzle_data
it->component_mask = it->component_mask | component_mask;
}
} catch (const std::out_of_range& ) {
- _dbg_assert_msg_(GPU, 0, "Unknown output attribute mapping");
- ERROR_LOG(GPU, "Unknown output attribute mapping: %03x, %03x, %03x, %03x",
+ _dbg_assert_msg_(HW_GPU, 0, "Unknown output attribute mapping");
+ LOG_ERROR(HW_GPU, "Unknown output attribute mapping: %03x, %03x, %03x, %03x",
(int)output_attributes[i].map_x.Value(),
(int)output_attributes[i].map_y.Value(),
(int)output_attributes[i].map_z.Value(),
@@ -265,7 +309,7 @@ static int is_pica_tracing = false;
void StartPicaTracing()
{
if (is_pica_tracing) {
- ERROR_LOG(GPU, "StartPicaTracing called even though tracing already running!");
+ LOG_WARNING(HW_GPU, "StartPicaTracing called even though tracing already running!");
return;
}
@@ -298,7 +342,7 @@ void OnPicaRegWrite(u32 id, u32 value)
std::unique_ptr<PicaTrace> FinishPicaTracing()
{
if (!is_pica_tracing) {
- ERROR_LOG(GPU, "FinishPicaTracing called even though tracing already running!");
+ LOG_WARNING(HW_GPU, "FinishPicaTracing called even though tracing isn't running!");
return {};
}
@@ -312,15 +356,51 @@ std::unique_ptr<PicaTrace> FinishPicaTracing()
return std::move(ret);
}
+const Math::Vec4<u8> LookupTexture(const u8* source, int x, int y, const TextureInfo& info) {
+ _dbg_assert_(Debug_GPU, info.format == Pica::Regs::TextureFormat::RGB8);
+
+ // Cf. rasterizer code for an explanation of this algorithm.
+ int texel_index_within_tile = 0;
+ for (int block_size_index = 0; block_size_index < 3; ++block_size_index) {
+ int sub_tile_width = 1 << block_size_index;
+ int sub_tile_height = 1 << block_size_index;
+
+ int sub_tile_index = (x & sub_tile_width) << block_size_index;
+ sub_tile_index += 2 * ((y & sub_tile_height) << block_size_index);
+ texel_index_within_tile += sub_tile_index;
+ }
+
+ const int block_width = 8;
+ const int block_height = 8;
+
+ int coarse_x = (x / block_width) * block_width;
+ int coarse_y = (y / block_height) * block_height;
+
+ const u8* source_ptr = source + coarse_x * block_height * 3 + coarse_y * info.stride + texel_index_within_tile * 3;
+ return { source_ptr[2], source_ptr[1], source_ptr[0], 255 };
+}
+
+TextureInfo TextureInfo::FromPicaRegister(const Regs::TextureConfig& config,
+ const Regs::TextureFormat& format)
+{
+ TextureInfo info;
+ info.address = config.GetPhysicalAddress();
+ info.width = config.width;
+ info.height = config.height;
+ info.format = format;
+ info.stride = Pica::Regs::BytesPerPixel(info.format) * info.width;
+ return info;
+}
+
void DumpTexture(const Pica::Regs::TextureConfig& texture_config, u8* data) {
// NOTE: Permanently enabling this just trashes hard disks for no reason.
// Hence, this is currently disabled.
return;
#ifndef HAVE_PNG
- return;
+ return;
#else
- if (!data)
+ if (!data)
return;
// Write data to file
@@ -341,7 +421,7 @@ void DumpTexture(const Pica::Regs::TextureConfig& texture_config, u8* data) {
// Initialize write structure
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
if (png_ptr == nullptr) {
- ERROR_LOG(GPU, "Could not allocate write struct\n");
+ LOG_ERROR(Debug_GPU, "Could not allocate write struct\n");
goto finalise;
}
@@ -349,13 +429,13 @@ void DumpTexture(const Pica::Regs::TextureConfig& texture_config, u8* data) {
// Initialize info structure
info_ptr = png_create_info_struct(png_ptr);
if (info_ptr == nullptr) {
- ERROR_LOG(GPU, "Could not allocate info struct\n");
+ LOG_ERROR(Debug_GPU, "Could not allocate info struct\n");
goto finalise;
}
// Setup Exception handling
if (setjmp(png_jmpbuf(png_ptr))) {
- ERROR_LOG(GPU, "Error during png creation\n");
+ LOG_ERROR(Debug_GPU, "Error during png creation\n");
goto finalise;
}
@@ -375,34 +455,22 @@ void DumpTexture(const Pica::Regs::TextureConfig& texture_config, u8* data) {
png_write_info(png_ptr, info_ptr);
buf = new u8[row_stride * texture_config.height];
- for (int y = 0; y < texture_config.height; ++y) {
- for (int x = 0; x < texture_config.width; ++x) {
- // Cf. rasterizer code for an explanation of this algorithm.
- int texel_index_within_tile = 0;
- for (int block_size_index = 0; block_size_index < 3; ++block_size_index) {
- int sub_tile_width = 1 << block_size_index;
- int sub_tile_height = 1 << block_size_index;
-
- int sub_tile_index = (x & sub_tile_width) << block_size_index;
- sub_tile_index += 2 * ((y & sub_tile_height) << block_size_index);
- texel_index_within_tile += sub_tile_index;
- }
-
- const int block_width = 8;
- const int block_height = 8;
-
- int coarse_x = (x / block_width) * block_width;
- int coarse_y = (y / block_height) * block_height;
-
- u8* source_ptr = (u8*)data + coarse_x * block_height * 3 + coarse_y * row_stride + texel_index_within_tile * 3;
- buf[3 * x + y * row_stride ] = source_ptr[2];
- buf[3 * x + y * row_stride + 1] = source_ptr[1];
- buf[3 * x + y * row_stride + 2] = source_ptr[0];
+ for (unsigned y = 0; y < texture_config.height; ++y) {
+ for (unsigned x = 0; x < texture_config.width; ++x) {
+ TextureInfo info;
+ info.width = texture_config.width;
+ info.height = texture_config.height;
+ info.stride = row_stride;
+ info.format = registers.texture0_format;
+ Math::Vec4<u8> texture_color = LookupTexture(data, x, y, info);
+ buf[3 * x + y * row_stride ] = texture_color.r();
+ buf[3 * x + y * row_stride + 1] = texture_color.g();
+ buf[3 * x + y * row_stride + 2] = texture_color.b();
}
}
// Write image data
- for (auto y = 0; y < texture_config.height; ++y)
+ for (unsigned y = 0; y < texture_config.height; ++y)
{
u8* row_ptr = (u8*)buf + y * row_stride;
u8* ptr = row_ptr;
@@ -514,7 +582,7 @@ void DumpTevStageConfig(const std::array<Pica::Regs::TevStageConfig,6>& stages)
stage_info += "Stage " + std::to_string(index) + ": " + GetColorCombinerStr(tev_stage) + " " + GetAlphaCombinerStr(tev_stage) + "\n";
}
- DEBUG_LOG(GPU, "%s", stage_info.c_str());
+ LOG_TRACE(HW_GPU, "%s", stage_info.c_str());
}
} // namespace
diff --git a/src/video_core/debug_utils/debug_utils.h b/src/video_core/debug_utils/debug_utils.h
index 8b1499bf2..51f14f12f 100644
--- a/src/video_core/debug_utils/debug_utils.h
+++ b/src/video_core/debug_utils/debug_utils.h
@@ -5,13 +5,147 @@
#pragma once
#include <array>
+#include <condition_variable>
+#include <list>
+#include <map>
#include <memory>
+#include <mutex>
#include <vector>
+#include "video_core/math.h"
#include "video_core/pica.h"
namespace Pica {
+class DebugContext {
+public:
+ enum class Event {
+ FirstEvent = 0,
+
+ CommandLoaded = FirstEvent,
+ CommandProcessed,
+ IncomingPrimitiveBatch,
+ FinishedPrimitiveBatch,
+
+ NumEvents
+ };
+
+ /**
+ * Inherit from this class to be notified of events registered to some debug context.
+ * Most importantly this is used for our debugger GUI.
+ *
+ * To implement event handling, override the OnPicaBreakPointHit and OnPicaResume methods.
+ * @warning All BreakPointObservers need to be on the same thread to guarantee thread-safe state access
+ * @todo Evaluate an alternative interface, in which there is only one managing observer and multiple child observers running (by design) on the same thread.
+ */
+ class BreakPointObserver {
+ public:
+ /// Constructs the object such that it observes events of the given DebugContext.
+ BreakPointObserver(std::shared_ptr<DebugContext> debug_context) : context_weak(debug_context) {
+ std::unique_lock<std::mutex> lock(debug_context->breakpoint_mutex);
+ debug_context->breakpoint_observers.push_back(this);
+ }
+
+ virtual ~BreakPointObserver() {
+ auto context = context_weak.lock();
+ if (context) {
+ std::unique_lock<std::mutex> lock(context->breakpoint_mutex);
+ context->breakpoint_observers.remove(this);
+
+ // If we are the last observer to be destroyed, tell the debugger context that
+ // it is free to continue. In particular, this is required for a proper Citra
+ // shutdown, when the emulation thread is waiting at a breakpoint.
+ if (context->breakpoint_observers.empty())
+ context->Resume();
+ }
+ }
+
+ /**
+ * Action to perform when a breakpoint was reached.
+ * @param event Type of event which triggered the breakpoint
+ * @param data Optional data pointer (if unused, this is a nullptr)
+ * @note This function will perform nothing unless it is overridden in the child class.
+ */
+ virtual void OnPicaBreakPointHit(Event, void*) {
+ }
+
+ /**
+ * Action to perform when emulation is resumed from a breakpoint.
+ * @note This function will perform nothing unless it is overridden in the child class.
+ */
+ virtual void OnPicaResume() {
+ }
+
+ protected:
+ /**
+ * Weak context pointer. This need not be valid, so when requesting a shared_ptr via
+ * context_weak.lock(), always compare the result against nullptr.
+ */
+ std::weak_ptr<DebugContext> context_weak;
+ };
+
+ /**
+ * Simple structure defining a breakpoint state
+ */
+ struct BreakPoint {
+ bool enabled = false;
+ };
+
+ /**
+ * Static constructor used to create a shared_ptr of a DebugContext.
+ */
+ static std::shared_ptr<DebugContext> Construct() {
+ return std::shared_ptr<DebugContext>(new DebugContext);
+ }
+
+ /**
+ * Used by the emulation core when a given event has happened. If a breakpoint has been set
+ * for this event, OnEvent calls the event handlers of the registered breakpoint observers.
+ * The current thread then is halted until Resume() is called from another thread (or until
+ * emulation is stopped).
+ * @param event Event which has happened
+ * @param data Optional data pointer (pass nullptr if unused). Needs to remain valid until Resume() is called.
+ */
+ void OnEvent(Event event, void* data);
+
+ /**
+ * Resume from the current breakpoint.
+ * @warning Calling this from the same thread that OnEvent was called in will cause a deadlock. Calling from any other thread is safe.
+ */
+ void Resume();
+
+ /**
+ * Delete all set breakpoints and resume emulation.
+ */
+ void ClearBreakpoints() {
+ breakpoints.clear();
+ Resume();
+ }
+
+ // TODO: Evaluate if access to these members should be hidden behind a public interface.
+ std::map<Event, BreakPoint> breakpoints;
+ Event active_breakpoint;
+ bool at_breakpoint = false;
+
+private:
+ /**
+ * Private default constructor to make sure people always construct this through Construct()
+ * instead.
+ */
+ DebugContext() = default;
+
+ /// Mutex protecting current breakpoint state and the observer list.
+ std::mutex breakpoint_mutex;
+
+ /// Used by OnEvent to wait for resumption.
+ std::condition_variable resume_from_breakpoint;
+
+ /// List of registered observers
+ std::list<BreakPointObserver*> breakpoint_observers;
+};
+
+extern std::shared_ptr<DebugContext> g_debug_context; // TODO: Get rid of this global
+
namespace DebugUtils {
// Simple utility class for dumping geometry data to an OBJ file
@@ -41,7 +175,7 @@ void DumpShader(const u32* binary_data, u32 binary_size, const u32* swizzle_data
// Utility class to log Pica commands.
struct PicaTrace {
struct Write : public std::pair<u32,u32> {
- Write(u32 id, u32 value) : std::pair<u32,u32>(id, value) {}
+ Write(u32 id, u32 value) : std::pair<u32,u32>(id, value) {}
u32& Id() { return first; }
const u32& Id() const { return first; }
@@ -57,6 +191,18 @@ bool IsPicaTracing();
void OnPicaRegWrite(u32 id, u32 value);
std::unique_ptr<PicaTrace> FinishPicaTracing();
+struct TextureInfo {
+ unsigned int address;
+ int width;
+ int height;
+ int stride;
+ Pica::Regs::TextureFormat format;
+
+ static TextureInfo FromPicaRegister(const Pica::Regs::TextureConfig& config,
+ const Pica::Regs::TextureFormat& format);
+};
+
+const Math::Vec4<u8> LookupTexture(const u8* source, int x, int y, const TextureInfo& info);
void DumpTexture(const Pica::Regs::TextureConfig& texture_config, u8* data);
void DumpTevStageConfig(const std::array<Pica::Regs::TevStageConfig,6>& stages);
diff --git a/src/video_core/gpu_debugger.h b/src/video_core/gpu_debugger.h
index 1242eb58f..16b1656bb 100644
--- a/src/video_core/gpu_debugger.h
+++ b/src/video_core/gpu_debugger.h
@@ -39,7 +39,7 @@ public:
virtual void GXCommandProcessed(int total_command_count)
{
const GSP_GPU::Command& cmd = observed->ReadGXCommandHistory(total_command_count-1);
- ERROR_LOG(GSP, "Received command: id=%x", (int)cmd.id.Value());
+ LOG_TRACE(Debug_GPU, "Received command: id=%x", (int)cmd.id.Value());
}
protected:
diff --git a/src/video_core/pica.h b/src/video_core/pica.h
index 5fe15a218..4c3791ad9 100644
--- a/src/video_core/pica.h
+++ b/src/video_core/pica.h
@@ -45,10 +45,16 @@ struct Regs {
#define INSERT_PADDING_WORDS_HELPER2(x, y) INSERT_PADDING_WORDS_HELPER1(x, y)
#define INSERT_PADDING_WORDS(num_words) u32 INSERT_PADDING_WORDS_HELPER2(pad, __LINE__)[(num_words)];
- INSERT_PADDING_WORDS(0x41);
+ INSERT_PADDING_WORDS(0x10);
+
+ u32 trigger_irq;
+
+ INSERT_PADDING_WORDS(0x30);
BitField<0, 24, u32> viewport_size_x;
+
INSERT_PADDING_WORDS(0x1);
+
BitField<0, 24, u32> viewport_size_y;
INSERT_PADDING_WORDS(0x9);
@@ -109,8 +115,8 @@ struct Regs {
u32 address;
- u32 GetPhysicalAddress() {
- return DecodeAddressRegister(address) - Memory::FCRAM_PADDR + Memory::HEAP_GSP_VADDR;
+ u32 GetPhysicalAddress() const {
+ return DecodeAddressRegister(address) - Memory::FCRAM_PADDR + Memory::HEAP_LINEAR_VADDR;
}
// texture1 and texture2 store the texture format directly after the address
@@ -130,7 +136,26 @@ struct Regs {
// Seems like they are luminance formats and compressed textures.
};
- BitField<0, 1, u32> texturing_enable;
+ static unsigned BytesPerPixel(TextureFormat format) {
+ switch (format) {
+ case TextureFormat::RGBA8:
+ return 4;
+
+ case TextureFormat::RGB8:
+ return 3;
+
+ case TextureFormat::RGBA5551:
+ case TextureFormat::RGB565:
+ case TextureFormat::RGBA4:
+ return 2;
+
+ default:
+ // placeholder for yet unknown formats
+ return 1;
+ }
+ }
+
+ BitField< 0, 1, u32> texturing_enable;
TextureConfig texture0;
INSERT_PADDING_WORDS(0x8);
BitField<0, 4, TextureFormat> texture0_format;
@@ -287,7 +312,7 @@ struct Regs {
inline u32 GetBaseAddress() const {
// TODO: Ugly, should fix PhysicalToVirtualAddress instead
- return DecodeAddressRegister(base_address) - Memory::FCRAM_PADDR + Memory::HEAP_GSP_VADDR;
+ return DecodeAddressRegister(base_address) - Memory::FCRAM_PADDR + Memory::HEAP_LINEAR_VADDR;
}
// Descriptor for internal vertex attributes
@@ -517,10 +542,6 @@ struct Regs {
static std::string GetCommandName(int index) {
std::map<u32, std::string> map;
- // TODO: MSVC does not support using offsetof() on non-static data members even though this
- // is technically allowed since C++11. Hence, this functionality is disabled until
- // MSVC properly supports it.
- #ifndef _MSC_VER
Regs regs;
#define ADD_FIELD(name) \
do { \
@@ -529,6 +550,7 @@ struct Regs {
map.insert({i, #name + std::string("+") + std::to_string(i-PICA_REG_INDEX(name))}); \
} while(false)
+ ADD_FIELD(trigger_irq);
ADD_FIELD(viewport_size_x);
ADD_FIELD(viewport_size_y);
ADD_FIELD(viewport_depth_range);
@@ -557,7 +579,6 @@ struct Regs {
ADD_FIELD(vs_swizzle_patterns);
#undef ADD_FIELD
- #endif // _MSC_VER
// Return empty string if no match is found
return map[index];
@@ -593,6 +614,7 @@ private:
#ifndef _MSC_VER
#define ASSERT_REG_POSITION(field_name, position) static_assert(offsetof(Regs, field_name) == position * 4, "Field "#field_name" has invalid position")
+ASSERT_REG_POSITION(trigger_irq, 0x10);
ASSERT_REG_POSITION(viewport_size_x, 0x41);
ASSERT_REG_POSITION(viewport_size_y, 0x43);
ASSERT_REG_POSITION(viewport_depth_range, 0x4d);
diff --git a/src/video_core/primitive_assembly.cpp b/src/video_core/primitive_assembly.cpp
index dabf2d1a3..102693ed9 100644
--- a/src/video_core/primitive_assembly.cpp
+++ b/src/video_core/primitive_assembly.cpp
@@ -43,7 +43,7 @@ void PrimitiveAssembler<VertexType>::SubmitVertex(VertexType& vtx, TriangleHandl
break;
default:
- ERROR_LOG(GPU, "Unknown triangle topology %x:", (int)topology);
+ LOG_ERROR(Render_Software, "Unknown triangle topology %x:", (int)topology);
break;
}
}
diff --git a/src/video_core/rasterizer.cpp b/src/video_core/rasterizer.cpp
index a35f0c0d8..b7e04a560 100644
--- a/src/video_core/rasterizer.cpp
+++ b/src/video_core/rasterizer.cpp
@@ -252,7 +252,7 @@ void ProcessTriangle(const VertexShader::OutputVertex& v0,
return combiner_output.rgb();
default:
- ERROR_LOG(GPU, "Unknown color combiner source %d\n", (int)source);
+ LOG_ERROR(HW_GPU, "Unknown color combiner source %d\n", (int)source);
return {};
}
};
@@ -272,7 +272,7 @@ void ProcessTriangle(const VertexShader::OutputVertex& v0,
return combiner_output.a();
default:
- ERROR_LOG(GPU, "Unknown alpha combiner source %d\n", (int)source);
+ LOG_ERROR(HW_GPU, "Unknown alpha combiner source %d\n", (int)source);
return 0;
}
};
@@ -283,7 +283,7 @@ void ProcessTriangle(const VertexShader::OutputVertex& v0,
case ColorModifier::SourceColor:
return values;
default:
- ERROR_LOG(GPU, "Unknown color factor %d\n", (int)factor);
+ LOG_ERROR(HW_GPU, "Unknown color factor %d\n", (int)factor);
return {};
}
};
@@ -293,7 +293,7 @@ void ProcessTriangle(const VertexShader::OutputVertex& v0,
case AlphaModifier::SourceAlpha:
return value;
default:
- ERROR_LOG(GPU, "Unknown color factor %d\n", (int)factor);
+ LOG_ERROR(HW_GPU, "Unknown color factor %d\n", (int)factor);
return 0;
}
};
@@ -307,7 +307,7 @@ void ProcessTriangle(const VertexShader::OutputVertex& v0,
return ((input[0] * input[1]) / 255).Cast<u8>();
default:
- ERROR_LOG(GPU, "Unknown color combiner operation %d\n", (int)op);
+ LOG_ERROR(HW_GPU, "Unknown color combiner operation %d\n", (int)op);
return {};
}
};
@@ -321,7 +321,7 @@ void ProcessTriangle(const VertexShader::OutputVertex& v0,
return input[0] * input[1] / 255;
default:
- ERROR_LOG(GPU, "Unknown alpha combiner operation %d\n", (int)op);
+ LOG_ERROR(HW_GPU, "Unknown alpha combiner operation %d\n", (int)op);
return 0;
}
};
diff --git a/src/video_core/renderer_base.h b/src/video_core/renderer_base.h
index f1dbc9d17..bce402b88 100644
--- a/src/video_core/renderer_base.h
+++ b/src/video_core/renderer_base.h
@@ -25,7 +25,7 @@ public:
/// Swap buffers (render frame)
virtual void SwapBuffers() = 0;
- /**
+ /**
* Set the emulator window to use for renderer
* @param window EmuWindow handle to emulator window to use for rendering
*/
diff --git a/src/video_core/renderer_opengl/gl_shader_util.cpp b/src/video_core/renderer_opengl/gl_shader_util.cpp
index a0eb0418c..d0f82e6cd 100644
--- a/src/video_core/renderer_opengl/gl_shader_util.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_util.cpp
@@ -20,9 +20,9 @@ GLuint LoadShaders(const char* vertex_shader, const char* fragment_shader) {
int info_log_length;
// Compile Vertex Shader
- DEBUG_LOG(GPU, "Compiling vertex shader.");
+ LOG_DEBUG(Render_OpenGL, "Compiling vertex shader...");
- glShaderSource(vertex_shader_id, 1, &vertex_shader, NULL);
+ glShaderSource(vertex_shader_id, 1, &vertex_shader, nullptr);
glCompileShader(vertex_shader_id);
// Check Vertex Shader
@@ -31,14 +31,18 @@ GLuint LoadShaders(const char* vertex_shader, const char* fragment_shader) {
if (info_log_length > 1) {
std::vector<char> vertex_shader_error(info_log_length);
- glGetShaderInfoLog(vertex_shader_id, info_log_length, NULL, &vertex_shader_error[0]);
- DEBUG_LOG(GPU, "%s", &vertex_shader_error[0]);
+ glGetShaderInfoLog(vertex_shader_id, info_log_length, nullptr, &vertex_shader_error[0]);
+ if (result) {
+ LOG_DEBUG(Render_OpenGL, "%s", &vertex_shader_error[0]);
+ } else {
+ LOG_ERROR(Render_OpenGL, "Error compiling vertex shader:\n%s", &vertex_shader_error[0]);
+ }
}
// Compile Fragment Shader
- DEBUG_LOG(GPU, "Compiling fragment shader.");
+ LOG_DEBUG(Render_OpenGL, "Compiling fragment shader...");
- glShaderSource(fragment_shader_id, 1, &fragment_shader, NULL);
+ glShaderSource(fragment_shader_id, 1, &fragment_shader, nullptr);
glCompileShader(fragment_shader_id);
// Check Fragment Shader
@@ -47,12 +51,16 @@ GLuint LoadShaders(const char* vertex_shader, const char* fragment_shader) {
if (info_log_length > 1) {
std::vector<char> fragment_shader_error(info_log_length);
- glGetShaderInfoLog(fragment_shader_id, info_log_length, NULL, &fragment_shader_error[0]);
- DEBUG_LOG(GPU, "%s", &fragment_shader_error[0]);
+ glGetShaderInfoLog(fragment_shader_id, info_log_length, nullptr, &fragment_shader_error[0]);
+ if (result) {
+ LOG_DEBUG(Render_OpenGL, "%s", &fragment_shader_error[0]);
+ } else {
+ LOG_ERROR(Render_OpenGL, "Error compiling fragment shader:\n%s", &fragment_shader_error[0]);
+ }
}
// Link the program
- DEBUG_LOG(GPU, "Linking program.");
+ LOG_DEBUG(Render_OpenGL, "Linking program...");
GLuint program_id = glCreateProgram();
glAttachShader(program_id, vertex_shader_id);
@@ -65,8 +73,12 @@ GLuint LoadShaders(const char* vertex_shader, const char* fragment_shader) {
if (info_log_length > 1) {
std::vector<char> program_error(info_log_length);
- glGetProgramInfoLog(program_id, info_log_length, NULL, &program_error[0]);
- DEBUG_LOG(GPU, "%s", &program_error[0]);
+ glGetProgramInfoLog(program_id, info_log_length, nullptr, &program_error[0]);
+ if (result) {
+ LOG_DEBUG(Render_OpenGL, "%s", &program_error[0]);
+ } else {
+ LOG_ERROR(Render_OpenGL, "Error linking shader:\n%s", &program_error[0]);
+ }
}
glDeleteShader(vertex_shader_id);
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp
index 8483f79be..e2caeeb8f 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.cpp
+++ b/src/video_core/renderer_opengl/renderer_opengl.cpp
@@ -61,7 +61,7 @@ void RendererOpenGL::SwapBuffers() {
for(int i : {0, 1}) {
const auto& framebuffer = GPU::g_regs.framebuffer_config[i];
- if (textures[i].width != framebuffer.width || textures[i].height != framebuffer.height) {
+ if (textures[i].width != (GLsizei)framebuffer.width || textures[i].height != (GLsizei)framebuffer.height) {
// Reallocate texture if the framebuffer size has changed.
// This is expected to not happen very often and hence should not be a
// performance problem.
@@ -90,7 +90,7 @@ void RendererOpenGL::LoadFBToActiveGLTexture(const GPU::Regs::FramebufferConfig&
const VAddr framebuffer_vaddr = Memory::PhysicalToVirtualAddress(
framebuffer.active_fb == 1 ? framebuffer.address_left2 : framebuffer.address_left1);
- DEBUG_LOG(GPU, "0x%08x bytes from 0x%08x(%dx%d), fmt %x",
+ LOG_TRACE(Render_OpenGL, "0x%08x bytes from 0x%08x(%dx%d), fmt %x",
framebuffer.stride * framebuffer.height,
framebuffer_vaddr, (int)framebuffer.width,
(int)framebuffer.height, (int)framebuffer.format);
@@ -98,15 +98,15 @@ void RendererOpenGL::LoadFBToActiveGLTexture(const GPU::Regs::FramebufferConfig&
const u8* framebuffer_data = Memory::GetPointer(framebuffer_vaddr);
// TODO: Handle other pixel formats
- _dbg_assert_msg_(RENDER, framebuffer.color_format == GPU::Regs::PixelFormat::RGB8,
+ _dbg_assert_msg_(Render_OpenGL, framebuffer.color_format == GPU::Regs::PixelFormat::RGB8,
"Unsupported 3DS pixel format.");
size_t pixel_stride = framebuffer.stride / 3;
// OpenGL only supports specifying a stride in units of pixels, not bytes, unfortunately
- _dbg_assert_(RENDER, pixel_stride * 3 == framebuffer.stride);
+ _dbg_assert_(Render_OpenGL, pixel_stride * 3 == framebuffer.stride);
// Ensure no bad interactions with GL_UNPACK_ALIGNMENT, which by default
// only allows rows to have a memory alignement of 4.
- _dbg_assert_(RENDER, pixel_stride % 4 == 0);
+ _dbg_assert_(Render_OpenGL, pixel_stride % 4 == 0);
glBindTexture(GL_TEXTURE_2D, texture.handle);
glPixelStorei(GL_UNPACK_ROW_LENGTH, (GLint)pixel_stride);
@@ -191,7 +191,8 @@ void RendererOpenGL::DrawSingleScreenRotated(const TextureInfo& texture, float x
* Draws the emulated screens to the emulator window.
*/
void RendererOpenGL::DrawScreens() {
- glViewport(0, 0, resolution_width, resolution_height);
+ auto viewport_extent = GetViewportExtent();
+ glViewport(viewport_extent.left, viewport_extent.top, viewport_extent.GetWidth(), viewport_extent.GetHeight()); // TODO: Or bottom?
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(program_id);
@@ -228,17 +229,45 @@ void RendererOpenGL::SetWindow(EmuWindow* window) {
render_window = window;
}
+MathUtil::Rectangle<unsigned> RendererOpenGL::GetViewportExtent() {
+ unsigned framebuffer_width;
+ unsigned framebuffer_height;
+ std::tie(framebuffer_width, framebuffer_height) = render_window->GetFramebufferSize();
+
+ float window_aspect_ratio = static_cast<float>(framebuffer_height) / framebuffer_width;
+ float emulation_aspect_ratio = static_cast<float>(resolution_height) / resolution_width;
+
+ MathUtil::Rectangle<unsigned> viewport_extent;
+ if (window_aspect_ratio > emulation_aspect_ratio) {
+ // Window is narrower than the emulation content => apply borders to the top and bottom
+ unsigned viewport_height = std::round(emulation_aspect_ratio * framebuffer_width);
+ viewport_extent.left = 0;
+ viewport_extent.top = (framebuffer_height - viewport_height) / 2;
+ viewport_extent.right = viewport_extent.left + framebuffer_width;
+ viewport_extent.bottom = viewport_extent.top + viewport_height;
+ } else {
+ // Otherwise, apply borders to the left and right sides of the window.
+ unsigned viewport_width = std::round(framebuffer_height / emulation_aspect_ratio);
+ viewport_extent.left = (framebuffer_width - viewport_width) / 2;
+ viewport_extent.top = 0;
+ viewport_extent.right = viewport_extent.left + viewport_width;
+ viewport_extent.bottom = viewport_extent.top + framebuffer_height;
+ }
+
+ return viewport_extent;
+}
+
/// Initialize the renderer
void RendererOpenGL::Init() {
render_window->MakeCurrent();
int err = ogl_LoadFunctions();
if (ogl_LOAD_SUCCEEDED != err) {
- ERROR_LOG(RENDER, "Failed to initialize GL functions! Exiting...");
+ LOG_CRITICAL(Render_OpenGL, "Failed to initialize GL functions! Exiting...");
exit(-1);
}
- NOTICE_LOG(RENDER, "GL_VERSION: %s\n", glGetString(GL_VERSION));
+ LOG_INFO(Render_OpenGL, "GL_VERSION: %s", glGetString(GL_VERSION));
InitOpenGLObjects();
}
diff --git a/src/video_core/renderer_opengl/renderer_opengl.h b/src/video_core/renderer_opengl/renderer_opengl.h
index eed201a95..7fdcec731 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.h
+++ b/src/video_core/renderer_opengl/renderer_opengl.h
@@ -4,13 +4,15 @@
#pragma once
+#include <array>
+
#include "generated/gl_3_2_core.h"
-#include "common/common.h"
+#include "common/math_util.h"
+
#include "core/hw/gpu.h"
-#include "video_core/renderer_base.h"
-#include <array>
+#include "video_core/renderer_base.h"
class EmuWindow;
@@ -52,6 +54,9 @@ private:
static void LoadFBToActiveGLTexture(const GPU::Regs::FramebufferConfig& framebuffer,
const TextureInfo& texture);
+ /// Computes the viewport rectangle
+ MathUtil::Rectangle<unsigned> GetViewportExtent();
+
EmuWindow* render_window; ///< Handle to render window
u32 last_mode; ///< Last render mode
diff --git a/src/video_core/utils.cpp b/src/video_core/utils.cpp
index c1848f923..f1156a493 100644
--- a/src/video_core/utils.cpp
+++ b/src/video_core/utils.cpp
@@ -20,7 +20,7 @@ namespace VideoCore {
void DumpTGA(std::string filename, short width, short height, u8* raw_data) {
TGAHeader hdr = {0, 0, 2, 0, 0, 0, 0, width, height, 24, 0};
FILE* fout = fopen(filename.c_str(), "wb");
-
+
fwrite(&hdr, sizeof(TGAHeader), 1, fout);
for (int y = 0; y < height; y++) {
@@ -30,7 +30,7 @@ void DumpTGA(std::string filename, short width, short height, u8* raw_data) {
putc(raw_data[(3 * (y * width)) + (3 * x) + 2], fout); // r
}
}
-
+
fclose(fout);
}
} // namespace
diff --git a/src/video_core/utils.h b/src/video_core/utils.h
index 9cb3d4d43..21380a908 100644
--- a/src/video_core/utils.h
+++ b/src/video_core/utils.h
@@ -12,24 +12,24 @@ namespace FormatPrecision {
/// Adjust RGBA8 color with RGBA6 precision
static inline u32 rgba8_with_rgba6(u32 src) {
- u32 color = src;
- color &= 0xFCFCFCFC;
- color |= (color >> 6) & 0x03030303;
- return color;
+ u32 color = src;
+ color &= 0xFCFCFCFC;
+ color |= (color >> 6) & 0x03030303;
+ return color;
}
/// Adjust RGBA8 color with RGB565 precision
static inline u32 rgba8_with_rgb565(u32 src) {
- u32 color = (src & 0xF8FCF8);
- color |= (color >> 5) & 0x070007;
- color |= (color >> 6) & 0x000300;
- color |= 0xFF000000;
- return color;
+ u32 color = (src & 0xF8FCF8);
+ color |= (color >> 5) & 0x070007;
+ color |= (color >> 6) & 0x000300;
+ color |= 0xFF000000;
+ return color;
}
/// Adjust Z24 depth value with Z16 precision
static inline u32 z24_with_z16(u32 src) {
- return (src & 0xFFFF00) | (src >> 16);
+ return (src & 0xFFFF00) | (src >> 16);
}
} // namespace
diff --git a/src/video_core/vertex_shader.cpp b/src/video_core/vertex_shader.cpp
index 96625791c..477e78cfe 100644
--- a/src/video_core/vertex_shader.cpp
+++ b/src/video_core/vertex_shader.cpp
@@ -2,11 +2,16 @@
// Licensed under GPLv2
// Refer to the license.txt file included.
+#include <boost/range/algorithm.hpp>
+
+#include <common/file_util.h>
+
+#include <core/mem_map.h>
+
+#include "debug_utils/debug_utils.h"
+
#include "pica.h"
#include "vertex_shader.h"
-#include "debug_utils/debug_utils.h"
-#include <core/mem_map.h>
-#include <common/file_util.h>
namespace Pica {
@@ -201,7 +206,7 @@ static void ProcessShaderCode(VertexShaderState& state) {
case Instruction::OpCode::CALL:
increment_pc = false;
- _dbg_assert_(GPU, state.call_stack_pointer - state.call_stack < sizeof(state.call_stack));
+ _dbg_assert_(HW_GPU, state.call_stack_pointer - state.call_stack < sizeof(state.call_stack));
*++state.call_stack_pointer = state.program_counter - shader_memory;
// TODO: Does this offset refer to the beginning of shader memory?
@@ -213,7 +218,7 @@ static void ProcessShaderCode(VertexShaderState& state) {
break;
default:
- ERROR_LOG(GPU, "Unhandled instruction: 0x%02x (%s): 0x%08x",
+ LOG_ERROR(HW_GPU, "Unhandled instruction: 0x%02x (%s): 0x%08x",
(int)instr.opcode.Value(), instr.GetOpCodeName().c_str(), instr.hex);
break;
}
@@ -238,7 +243,7 @@ OutputVertex RunShader(const InputVertex& input, int num_attributes)
// Setup input register table
const auto& attribute_register_map = registers.vs_input_register_map;
float24 dummy_register;
- std::fill(&state.input_register_table[0], &state.input_register_table[16], &dummy_register);
+ boost::fill(state.input_register_table, &dummy_register);
if(num_attributes > 0) state.input_register_table[attribute_register_map.attribute0_register] = &input.attr[0].x;
if(num_attributes > 1) state.input_register_table[attribute_register_map.attribute1_register] = &input.attr[1].x;
if(num_attributes > 2) state.input_register_table[attribute_register_map.attribute2_register] = &input.attr[2].x;
@@ -272,8 +277,7 @@ OutputVertex RunShader(const InputVertex& input, int num_attributes)
state.status_registers[0] = false;
state.status_registers[1] = false;
- std::fill(state.call_stack, state.call_stack + sizeof(state.call_stack) / sizeof(state.call_stack[0]),
- VertexShaderState::INVALID_ADDRESS);
+ boost::fill(state.call_stack, VertexShaderState::INVALID_ADDRESS);
state.call_stack_pointer = &state.call_stack[0];
ProcessShaderCode(state);
@@ -281,7 +285,7 @@ OutputVertex RunShader(const InputVertex& input, int num_attributes)
state.debug.max_opdesc_id, registers.vs_main_offset,
registers.vs_output_attributes);
- DEBUG_LOG(GPU, "Output vertex: pos (%.2f, %.2f, %.2f, %.2f), col(%.2f, %.2f, %.2f, %.2f), tc0(%.2f, %.2f)",
+ LOG_TRACE(Render_Software, "Output vertex: pos (%.2f, %.2f, %.2f, %.2f), col(%.2f, %.2f, %.2f, %.2f), tc0(%.2f, %.2f)",
ret.pos.x.ToFloat32(), ret.pos.y.ToFloat32(), ret.pos.z.ToFloat32(), ret.pos.w.ToFloat32(),
ret.color.x.ToFloat32(), ret.color.y.ToFloat32(), ret.color.z.ToFloat32(), ret.color.w.ToFloat32(),
ret.tc0.u().ToFloat32(), ret.tc0.v().ToFloat32());
diff --git a/src/video_core/vertex_shader.h b/src/video_core/vertex_shader.h
index 607a8e803..bfb6fb6e3 100644
--- a/src/video_core/vertex_shader.h
+++ b/src/video_core/vertex_shader.h
@@ -141,7 +141,7 @@ union Instruction {
return BitFieldType::Value();
else if (GetRegisterType() == Temporary)
return BitFieldType::Value() - 0x10;
- else if (GetRegisterType() == FloatUniform)
+ else // if (GetRegisterType() == FloatUniform)
return BitFieldType::Value() - 0x20;
}
diff --git a/src/video_core/video_core.cpp b/src/video_core/video_core.cpp
index c779771c5..6791e4007 100644
--- a/src/video_core/video_core.cpp
+++ b/src/video_core/video_core.cpp
@@ -17,8 +17,8 @@
namespace VideoCore {
-EmuWindow* g_emu_window = NULL; ///< Frontend emulator window
-RendererBase* g_renderer = NULL; ///< Renderer plugin
+EmuWindow* g_emu_window = nullptr; ///< Frontend emulator window
+RendererBase* g_renderer = nullptr; ///< Renderer plugin
int g_current_frame = 0;
/// Initialize the video core
@@ -30,13 +30,13 @@ void Init(EmuWindow* emu_window) {
g_current_frame = 0;
- NOTICE_LOG(VIDEO, "initialized OK");
+ LOG_DEBUG(Render, "initialized OK");
}
/// Shutdown the video core
void Shutdown() {
delete g_renderer;
- NOTICE_LOG(VIDEO, "shutdown OK");
+ LOG_DEBUG(Render, "shutdown OK");
}
} // namespace