video_core: fixed arithmetic overflow warnings & improved code style

- Fixed all warnings, for renderer_opengl items, which were indicating a
possible incorrect behavior from integral promotion rules and types
larger than those in which arithmetic is typically performed.
- Added const for variables where possible and meaningful.
- Added constexpr where possible.
merge-requests/60/head
Patrick Elsässer 2018-09-09 17:51:43 +07:00
parent 6d64ecf359
commit 64e45b04e0
5 changed files with 101 additions and 89 deletions

@ -505,7 +505,7 @@ static void ConvertS8Z24ToZ24S8(std::vector<u8>& data, u32 width, u32 height) {
S8Z24 input_pixel{}; S8Z24 input_pixel{};
Z24S8 output_pixel{}; Z24S8 output_pixel{};
const auto bpp{CachedSurface::GetGLBytesPerPixel(PixelFormat::S8Z24)}; constexpr auto bpp{CachedSurface::GetGLBytesPerPixel(PixelFormat::S8Z24)};
for (size_t y = 0; y < height; ++y) { for (size_t y = 0; y < height; ++y) {
for (size_t x = 0; x < width; ++x) { for (size_t x = 0; x < width; ++x) {
const size_t offset{bpp * (y * width + x)}; const size_t offset{bpp * (y * width + x)};
@ -518,7 +518,7 @@ static void ConvertS8Z24ToZ24S8(std::vector<u8>& data, u32 width, u32 height) {
} }
static void ConvertG8R8ToR8G8(std::vector<u8>& data, u32 width, u32 height) { static void ConvertG8R8ToR8G8(std::vector<u8>& data, u32 width, u32 height) {
const auto bpp{CachedSurface::GetGLBytesPerPixel(PixelFormat::G8R8U)}; constexpr auto bpp{CachedSurface::GetGLBytesPerPixel(PixelFormat::G8R8U)};
for (size_t y = 0; y < height; ++y) { for (size_t y = 0; y < height; ++y) {
for (size_t x = 0; x < width; ++x) { for (size_t x = 0; x < width; ++x) {
const size_t offset{bpp * (y * width + x)}; const size_t offset{bpp * (y * width + x)};
@ -584,12 +584,13 @@ void CachedSurface::LoadGLBuffer() {
UNREACHABLE(); UNREACHABLE();
} }
gl_buffer.resize(params.depth * copy_size); gl_buffer.resize(static_cast<size_t>(params.depth) * copy_size);
morton_to_gl_fns[static_cast<size_t>(params.pixel_format)]( morton_to_gl_fns[static_cast<size_t>(params.pixel_format)](
params.width, params.block_height, params.height, gl_buffer.data(), copy_size, params.width, params.block_height, params.height, gl_buffer.data(), copy_size,
params.addr); params.addr);
} else { } else {
const u8* const texture_src_data_end{texture_src_data + (params.depth * copy_size)}; const u8* const texture_src_data_end{texture_src_data +
(static_cast<size_t>(params.depth) * copy_size)};
gl_buffer.assign(texture_src_data, texture_src_data_end); gl_buffer.assign(texture_src_data, texture_src_data_end);
} }
@ -608,18 +609,20 @@ void CachedSurface::UploadGLTexture(GLuint read_fb_handle, GLuint draw_fb_handle
MICROPROFILE_SCOPE(OpenGL_TextureUL); MICROPROFILE_SCOPE(OpenGL_TextureUL);
ASSERT(gl_buffer.size() == ASSERT(gl_buffer.size() == static_cast<size_t>(params.width) * params.height *
params.width * params.height * GetGLBytesPerPixel(params.pixel_format) * params.depth); GetGLBytesPerPixel(params.pixel_format) * params.depth);
const auto& rect{params.GetRect()}; const auto& rect{params.GetRect()};
// Load data from memory to the surface // Load data from memory to the surface
GLint x0 = static_cast<GLint>(rect.left); const GLint x0 = static_cast<GLint>(rect.left);
GLint y0 = static_cast<GLint>(rect.bottom); const GLint y0 = static_cast<GLint>(rect.bottom);
size_t buffer_offset = (y0 * params.width + x0) * GetGLBytesPerPixel(params.pixel_format); const size_t buffer_offset =
static_cast<size_t>(static_cast<size_t>(y0) * params.width + static_cast<size_t>(x0)) *
GetGLBytesPerPixel(params.pixel_format);
const FormatTuple& tuple = GetFormatTuple(params.pixel_format, params.component_type); const FormatTuple& tuple = GetFormatTuple(params.pixel_format, params.component_type);
GLuint target_tex = texture.handle; const GLuint target_tex = texture.handle;
OpenGLState cur_state = OpenGLState::GetCurState(); OpenGLState cur_state = OpenGLState::GetCurState();
const auto& old_tex = cur_state.texture_units[0]; const auto& old_tex = cur_state.texture_units[0];

@ -13,8 +13,8 @@ namespace OpenGL {
/// Gets the address for the specified shader stage program /// Gets the address for the specified shader stage program
static VAddr GetShaderAddress(Maxwell::ShaderProgram program) { static VAddr GetShaderAddress(Maxwell::ShaderProgram program) {
auto& gpu = Core::System::GetInstance().GPU().Maxwell3D(); const auto& gpu = Core::System::GetInstance().GPU().Maxwell3D();
auto& shader_config = gpu.regs.shader_config[static_cast<size_t>(program)]; const auto& shader_config = gpu.regs.shader_config[static_cast<size_t>(program)];
return *gpu.memory_manager.GpuToCpuAddress(gpu.regs.code_address.CodeAddress() + return *gpu.memory_manager.GpuToCpuAddress(gpu.regs.code_address.CodeAddress() +
shader_config.offset); shader_config.offset);
} }
@ -86,7 +86,7 @@ CachedShader::CachedShader(VAddr addr, Maxwell::ShaderProgram program_type)
} }
GLuint CachedShader::GetProgramResourceIndex(const GLShader::ConstBufferEntry& buffer) { GLuint CachedShader::GetProgramResourceIndex(const GLShader::ConstBufferEntry& buffer) {
auto search{resource_cache.find(buffer.GetHash())}; const auto search{resource_cache.find(buffer.GetHash())};
if (search == resource_cache.end()) { if (search == resource_cache.end()) {
const GLuint index{ const GLuint index{
glGetProgramResourceIndex(program.handle, GL_UNIFORM_BLOCK, buffer.GetName().c_str())}; glGetProgramResourceIndex(program.handle, GL_UNIFORM_BLOCK, buffer.GetName().c_str())};
@ -98,7 +98,7 @@ GLuint CachedShader::GetProgramResourceIndex(const GLShader::ConstBufferEntry& b
} }
GLint CachedShader::GetUniformLocation(const GLShader::SamplerEntry& sampler) { GLint CachedShader::GetUniformLocation(const GLShader::SamplerEntry& sampler) {
auto search{uniform_cache.find(sampler.GetHash())}; const auto search{uniform_cache.find(sampler.GetHash())};
if (search == uniform_cache.end()) { if (search == uniform_cache.end()) {
const GLint index{glGetUniformLocation(program.handle, sampler.GetName().c_str())}; const GLint index{glGetUniformLocation(program.handle, sampler.GetName().c_str())};
uniform_cache[sampler.GetHash()] = index; uniform_cache[sampler.GetHash()] = index;

@ -113,7 +113,7 @@ private:
/// Scans a range of code for labels and determines the exit method. /// Scans a range of code for labels and determines the exit method.
ExitMethod Scan(u32 begin, u32 end, std::set<u32>& labels) { ExitMethod Scan(u32 begin, u32 end, std::set<u32>& labels) {
auto [iter, inserted] = const auto [iter, inserted] =
exit_method_map.emplace(std::make_pair(begin, end), ExitMethod::Undetermined); exit_method_map.emplace(std::make_pair(begin, end), ExitMethod::Undetermined);
ExitMethod& exit_method = iter->second; ExitMethod& exit_method = iter->second;
if (!inserted) if (!inserted)
@ -131,22 +131,22 @@ private:
if (instr.pred.pred_index == static_cast<u64>(Pred::UnusedIndex)) { if (instr.pred.pred_index == static_cast<u64>(Pred::UnusedIndex)) {
return exit_method = ExitMethod::AlwaysEnd; return exit_method = ExitMethod::AlwaysEnd;
} else { } else {
ExitMethod not_met = Scan(offset + 1, end, labels); const ExitMethod not_met = Scan(offset + 1, end, labels);
return exit_method = ParallelExit(ExitMethod::AlwaysEnd, not_met); return exit_method = ParallelExit(ExitMethod::AlwaysEnd, not_met);
} }
} }
case OpCode::Id::BRA: { case OpCode::Id::BRA: {
u32 target = offset + instr.bra.GetBranchTarget(); const u32 target = offset + instr.bra.GetBranchTarget();
labels.insert(target); labels.insert(target);
ExitMethod no_jmp = Scan(offset + 1, end, labels); const ExitMethod no_jmp = Scan(offset + 1, end, labels);
ExitMethod jmp = Scan(target, end, labels); const ExitMethod jmp = Scan(target, end, labels);
return exit_method = ParallelExit(no_jmp, jmp); return exit_method = ParallelExit(no_jmp, jmp);
} }
case OpCode::Id::SSY: { case OpCode::Id::SSY: {
// The SSY instruction uses a similar encoding as the BRA instruction. // The SSY instruction uses a similar encoding as the BRA instruction.
ASSERT_MSG(instr.bra.constant_buffer == 0, ASSERT_MSG(instr.bra.constant_buffer == 0,
"Constant buffer SSY is not supported"); "Constant buffer SSY is not supported");
u32 target = offset + instr.bra.GetBranchTarget(); const u32 target = offset + instr.bra.GetBranchTarget();
labels.insert(target); labels.insert(target);
// Continue scanning for an exit method. // Continue scanning for an exit method.
break; break;
@ -346,8 +346,8 @@ public:
*/ */
void SetRegisterToInputAttibute(const Register& reg, u64 elem, Attribute::Index attribute, void SetRegisterToInputAttibute(const Register& reg, u64 elem, Attribute::Index attribute,
const Tegra::Shader::IpaMode& input_mode) { const Tegra::Shader::IpaMode& input_mode) {
std::string dest = GetRegisterAsFloat(reg); const std::string dest = GetRegisterAsFloat(reg);
std::string src = GetInputAttribute(attribute, input_mode) + GetSwizzle(elem); const std::string src = GetInputAttribute(attribute, input_mode) + GetSwizzle(elem);
shader.AddLine(dest + " = " + src + ';'); shader.AddLine(dest + " = " + src + ';');
} }
@ -359,8 +359,8 @@ public:
* @param reg The register to use as the source value. * @param reg The register to use as the source value.
*/ */
void SetOutputAttributeToRegister(Attribute::Index attribute, u64 elem, const Register& reg) { void SetOutputAttributeToRegister(Attribute::Index attribute, u64 elem, const Register& reg) {
std::string dest = GetOutputAttribute(attribute); const std::string dest = GetOutputAttribute(attribute);
std::string src = GetRegisterAsFloat(reg); const std::string src = GetRegisterAsFloat(reg);
if (!dest.empty()) { if (!dest.empty()) {
// Can happen with unknown/unimplemented output attributes, in which case we ignore the // Can happen with unknown/unimplemented output attributes, in which case we ignore the
@ -393,8 +393,8 @@ public:
GLSLRegister::Type type) { GLSLRegister::Type type) {
declr_const_buffers[cbuf_index].MarkAsUsedIndirect(cbuf_index, stage); declr_const_buffers[cbuf_index].MarkAsUsedIndirect(cbuf_index, stage);
std::string final_offset = fmt::format("({} + {})", index_str, offset / 4); const std::string final_offset = fmt::format("({} + {})", index_str, offset / 4);
std::string value = 'c' + std::to_string(cbuf_index) + '[' + final_offset + " / 4][" + const std::string value = 'c' + std::to_string(cbuf_index) + '[' + final_offset + " / 4][" +
final_offset + " % 4]"; final_offset + " % 4]";
if (type == GLSLRegister::Type::Float) { if (type == GLSLRegister::Type::Float) {
@ -468,10 +468,10 @@ public:
/// necessary. /// necessary.
std::string AccessSampler(const Sampler& sampler, Tegra::Shader::TextureType type, std::string AccessSampler(const Sampler& sampler, Tegra::Shader::TextureType type,
bool is_array) { bool is_array) {
size_t offset = static_cast<size_t>(sampler.index.Value()); const size_t offset = static_cast<size_t>(sampler.index.Value());
// If this sampler has already been used, return the existing mapping. // If this sampler has already been used, return the existing mapping.
auto itr = const auto itr =
std::find_if(used_samplers.begin(), used_samplers.end(), std::find_if(used_samplers.begin(), used_samplers.end(),
[&](const SamplerEntry& entry) { return entry.GetOffset() == offset; }); [&](const SamplerEntry& entry) { return entry.GetOffset() == offset; });
@ -481,8 +481,8 @@ public:
} }
// Otherwise create a new mapping for this sampler // Otherwise create a new mapping for this sampler
size_t next_index = used_samplers.size(); const size_t next_index = used_samplers.size();
SamplerEntry entry{stage, offset, next_index, type, is_array}; const SamplerEntry entry{stage, offset, next_index, type, is_array};
used_samplers.emplace_back(entry); used_samplers.emplace_back(entry);
return entry.GetName(); return entry.GetName();
} }
@ -699,7 +699,7 @@ private:
}; };
bool IsColorComponentOutputEnabled(u32 render_target, u32 component) const { bool IsColorComponentOutputEnabled(u32 render_target, u32 component) const {
u32 bit = render_target * 4 + component; const u32 bit = render_target * 4 + component;
return enabled_color_outputs & (1 << bit); return enabled_color_outputs & (1 << bit);
} }
}; };
@ -707,7 +707,7 @@ private:
/// Gets the Subroutine object corresponding to the specified address. /// Gets the Subroutine object corresponding to the specified address.
const Subroutine& GetSubroutine(u32 begin, u32 end) const { const Subroutine& GetSubroutine(u32 begin, u32 end) const {
auto iter = subroutines.find(Subroutine{begin, end, suffix}); const auto iter = subroutines.find(Subroutine{begin, end, suffix});
ASSERT(iter != subroutines.end()); ASSERT(iter != subroutines.end());
return *iter; return *iter;
} }
@ -752,7 +752,7 @@ private:
// Can't assign to the constant predicate. // Can't assign to the constant predicate.
ASSERT(pred != static_cast<u64>(Pred::UnusedIndex)); ASSERT(pred != static_cast<u64>(Pred::UnusedIndex));
std::string variable = 'p' + std::to_string(pred) + '_' + suffix; const std::string variable = 'p' + std::to_string(pred) + '_' + suffix;
shader.AddLine(variable + " = " + value + ';'); shader.AddLine(variable + " = " + value + ';');
declr_predicates.insert(std::move(variable)); declr_predicates.insert(std::move(variable));
} }
@ -1033,7 +1033,11 @@ private:
if (header.writes_depth) { if (header.writes_depth) {
// The depth output is always 2 registers after the last color output, and current_reg // The depth output is always 2 registers after the last color output, and current_reg
// already contains one past the last color register. // already contains one past the last color register.
shader.AddLine("gl_FragDepth = " + regs.GetRegisterAsFloat(current_reg + 1) + ';');
shader.AddLine(
"gl_FragDepth = " +
regs.GetRegisterAsFloat(static_cast<Tegra::Shader::Register>(current_reg) + 1) +
';');
} }
} }
@ -1435,7 +1439,7 @@ private:
if (instr.alu_integer.negate_b) if (instr.alu_integer.negate_b)
op_b = "-(" + op_b + ')'; op_b = "-(" + op_b + ')';
std::string shift = std::to_string(instr.alu_integer.shift_amount.Value()); const std::string shift = std::to_string(instr.alu_integer.shift_amount.Value());
regs.SetRegisterToInteger(instr.gpr0, true, 0, regs.SetRegisterToInteger(instr.gpr0, true, 0,
"((" + op_a + " << " + shift + ") + " + op_b + ')', 1, 1); "((" + op_a + " << " + shift + ") + " + op_b + ')', 1, 1);
@ -1453,7 +1457,7 @@ private:
case OpCode::Id::SEL_C: case OpCode::Id::SEL_C:
case OpCode::Id::SEL_R: case OpCode::Id::SEL_R:
case OpCode::Id::SEL_IMM: { case OpCode::Id::SEL_IMM: {
std::string condition = const std::string condition =
GetPredicateCondition(instr.sel.pred, instr.sel.neg_pred != 0); GetPredicateCondition(instr.sel.pred, instr.sel.neg_pred != 0);
regs.SetRegisterToInteger(instr.gpr0, true, 0, regs.SetRegisterToInteger(instr.gpr0, true, 0,
'(' + condition + ") ? " + op_a + " : " + op_b, 1, 1); '(' + condition + ") ? " + op_a + " : " + op_b, 1, 1);
@ -1475,8 +1479,9 @@ private:
case OpCode::Id::LOP3_C: case OpCode::Id::LOP3_C:
case OpCode::Id::LOP3_R: case OpCode::Id::LOP3_R:
case OpCode::Id::LOP3_IMM: { case OpCode::Id::LOP3_IMM: {
std::string op_c = regs.GetRegisterAsInteger(instr.gpr39); const std::string op_c = regs.GetRegisterAsInteger(instr.gpr39);
std::string lut; std::string lut;
if (opcode->GetId() == OpCode::Id::LOP3_R) { if (opcode->GetId() == OpCode::Id::LOP3_R) {
lut = '(' + std::to_string(instr.alu.lop3.GetImmLut28()) + ')'; lut = '(' + std::to_string(instr.alu.lop3.GetImmLut28()) + ')';
} else { } else {
@ -1491,9 +1496,9 @@ private:
case OpCode::Id::IMNMX_IMM: { case OpCode::Id::IMNMX_IMM: {
ASSERT_MSG(instr.imnmx.exchange == Tegra::Shader::IMinMaxExchange::None, ASSERT_MSG(instr.imnmx.exchange == Tegra::Shader::IMinMaxExchange::None,
"Unimplemented"); "Unimplemented");
std::string condition = const std::string condition =
GetPredicateCondition(instr.imnmx.pred, instr.imnmx.negate_pred != 0); GetPredicateCondition(instr.imnmx.pred, instr.imnmx.negate_pred != 0);
std::string parameters = op_a + ',' + op_b; const std::string parameters = op_a + ',' + op_b;
regs.SetRegisterToInteger(instr.gpr0, instr.imnmx.is_signed, 0, regs.SetRegisterToInteger(instr.gpr0, instr.imnmx.is_signed, 0,
'(' + condition + ") ? min(" + parameters + ") : max(" + '(' + condition + ") ? min(" + parameters + ") : max(" +
parameters + ')', parameters + ')',
@ -1510,7 +1515,7 @@ private:
break; break;
} }
case OpCode::Type::Ffma: { case OpCode::Type::Ffma: {
std::string op_a = regs.GetRegisterAsFloat(instr.gpr8); const std::string op_a = regs.GetRegisterAsFloat(instr.gpr8);
std::string op_b = instr.ffma.negate_b ? "-" : ""; std::string op_b = instr.ffma.negate_b ? "-" : "";
std::string op_c = instr.ffma.negate_c ? "-" : ""; std::string op_c = instr.ffma.negate_c ? "-" : "";
@ -1720,7 +1725,7 @@ private:
shader.AddLine("uint index = (" + regs.GetRegisterAsInteger(instr.gpr8, 0, false) + shader.AddLine("uint index = (" + regs.GetRegisterAsInteger(instr.gpr8, 0, false) +
" / 4) & (MAX_CONSTBUFFER_ELEMENTS - 1);"); " / 4) & (MAX_CONSTBUFFER_ELEMENTS - 1);");
std::string op_a = const std::string op_a =
regs.GetUniformIndirect(instr.cbuf36.index, instr.cbuf36.offset + 0, "index", regs.GetUniformIndirect(instr.cbuf36.index, instr.cbuf36.offset + 0, "index",
GLSLRegister::Type::Float); GLSLRegister::Type::Float);
@ -1730,7 +1735,7 @@ private:
break; break;
case Tegra::Shader::UniformType::Double: { case Tegra::Shader::UniformType::Double: {
std::string op_b = const std::string op_b =
regs.GetUniformIndirect(instr.cbuf36.index, instr.cbuf36.offset + 4, regs.GetUniformIndirect(instr.cbuf36.index, instr.cbuf36.offset + 4,
"index", GLSLRegister::Type::Float); "index", GLSLRegister::Type::Float);
regs.SetRegisterToFloat(instr.gpr0, 0, op_a, 1, 1); regs.SetRegisterToFloat(instr.gpr0, 0, op_a, 1, 1);
@ -1760,13 +1765,13 @@ private:
switch (texture_type) { switch (texture_type) {
case Tegra::Shader::TextureType::Texture1D: { case Tegra::Shader::TextureType::Texture1D: {
std::string x = regs.GetRegisterAsFloat(instr.gpr8); const std::string x = regs.GetRegisterAsFloat(instr.gpr8);
coord = "float coords = " + x + ';'; coord = "float coords = " + x + ';';
break; break;
} }
case Tegra::Shader::TextureType::Texture2D: { case Tegra::Shader::TextureType::Texture2D: {
std::string x = regs.GetRegisterAsFloat(instr.gpr8); const std::string x = regs.GetRegisterAsFloat(instr.gpr8);
std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); const std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1);
coord = "vec2 coords = vec2(" + x + ", " + y + ");"; coord = "vec2 coords = vec2(" + x + ", " + y + ");";
break; break;
} }
@ -1776,8 +1781,8 @@ private:
UNREACHABLE(); UNREACHABLE();
// Fallback to interpreting as a 2D texture for now // Fallback to interpreting as a 2D texture for now
std::string x = regs.GetRegisterAsFloat(instr.gpr8); const std::string x = regs.GetRegisterAsFloat(instr.gpr8);
std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); const std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1);
coord = "vec2 coords = vec2(" + x + ", " + y + ");"; coord = "vec2 coords = vec2(" + x + ", " + y + ");";
texture_type = Tegra::Shader::TextureType::Texture2D; texture_type = Tegra::Shader::TextureType::Texture2D;
} }
@ -1811,13 +1816,13 @@ private:
switch (texture_type) { switch (texture_type) {
case Tegra::Shader::TextureType::Texture2D: { case Tegra::Shader::TextureType::Texture2D: {
if (is_array) { if (is_array) {
std::string index = regs.GetRegisterAsInteger(instr.gpr8); const std::string index = regs.GetRegisterAsInteger(instr.gpr8);
std::string x = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); const std::string x = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1);
std::string y = regs.GetRegisterAsFloat(instr.gpr20); const std::string y = regs.GetRegisterAsFloat(instr.gpr20);
coord = "vec3 coords = vec3(" + x + ", " + y + ", " + index + ");"; coord = "vec3 coords = vec3(" + x + ", " + y + ", " + index + ");";
} else { } else {
std::string x = regs.GetRegisterAsFloat(instr.gpr8); const std::string x = regs.GetRegisterAsFloat(instr.gpr8);
std::string y = regs.GetRegisterAsFloat(instr.gpr20); const std::string y = regs.GetRegisterAsFloat(instr.gpr20);
coord = "vec2 coords = vec2(" + x + ", " + y + ");"; coord = "vec2 coords = vec2(" + x + ", " + y + ");";
} }
break; break;
@ -1828,8 +1833,8 @@ private:
UNREACHABLE(); UNREACHABLE();
// Fallback to interpreting as a 2D texture for now // Fallback to interpreting as a 2D texture for now
std::string x = regs.GetRegisterAsFloat(instr.gpr8); const std::string x = regs.GetRegisterAsFloat(instr.gpr8);
std::string y = regs.GetRegisterAsFloat(instr.gpr20); const std::string y = regs.GetRegisterAsFloat(instr.gpr20);
coord = "vec2 coords = vec2(" + x + ", " + y + ");"; coord = "vec2 coords = vec2(" + x + ", " + y + ");";
texture_type = Tegra::Shader::TextureType::Texture2D; texture_type = Tegra::Shader::TextureType::Texture2D;
is_array = false; is_array = false;
@ -1850,8 +1855,8 @@ private:
LOG_CRITICAL(HW_GPU, "Unhandled 2d array texture"); LOG_CRITICAL(HW_GPU, "Unhandled 2d array texture");
UNREACHABLE(); UNREACHABLE();
} else { } else {
std::string x = regs.GetRegisterAsInteger(instr.gpr8); const std::string x = regs.GetRegisterAsInteger(instr.gpr8);
std::string y = regs.GetRegisterAsInteger(instr.gpr20); const std::string y = regs.GetRegisterAsInteger(instr.gpr20);
coord = "ivec2 coords = ivec2(" + x + ", " + y + ");"; coord = "ivec2 coords = ivec2(" + x + ", " + y + ");";
} }
break; break;
@ -1874,8 +1879,8 @@ private:
switch (instr.tld4.texture_type) { switch (instr.tld4.texture_type) {
case Tegra::Shader::TextureType::Texture2D: { case Tegra::Shader::TextureType::Texture2D: {
std::string x = regs.GetRegisterAsFloat(instr.gpr8); const std::string x = regs.GetRegisterAsFloat(instr.gpr8);
std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); const std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1);
coord = "vec2 coords = vec2(" + x + ", " + y + ");"; coord = "vec2 coords = vec2(" + x + ", " + y + ");";
break; break;
} }
@ -1959,12 +1964,12 @@ private:
// We can't use the constant predicate as destination. // We can't use the constant predicate as destination.
ASSERT(instr.fsetp.pred3 != static_cast<u64>(Pred::UnusedIndex)); ASSERT(instr.fsetp.pred3 != static_cast<u64>(Pred::UnusedIndex));
std::string second_pred = const std::string second_pred =
GetPredicateCondition(instr.fsetp.pred39, instr.fsetp.neg_pred != 0); GetPredicateCondition(instr.fsetp.pred39, instr.fsetp.neg_pred != 0);
std::string combiner = GetPredicateCombiner(instr.fsetp.op); const std::string combiner = GetPredicateCombiner(instr.fsetp.op);
std::string predicate = GetPredicateComparison(instr.fsetp.cond, op_a, op_b); const std::string predicate = GetPredicateComparison(instr.fsetp.cond, op_a, op_b);
// Set the primary predicate to the result of Predicate OP SecondPredicate // Set the primary predicate to the result of Predicate OP SecondPredicate
SetPredicate(instr.fsetp.pred3, SetPredicate(instr.fsetp.pred3,
'(' + predicate + ") " + combiner + " (" + second_pred + ')'); '(' + predicate + ") " + combiner + " (" + second_pred + ')');
@ -1978,7 +1983,8 @@ private:
break; break;
} }
case OpCode::Type::IntegerSetPredicate: { case OpCode::Type::IntegerSetPredicate: {
std::string op_a = regs.GetRegisterAsInteger(instr.gpr8, 0, instr.isetp.is_signed); const std::string op_a =
regs.GetRegisterAsInteger(instr.gpr8, 0, instr.isetp.is_signed);
std::string op_b; std::string op_b;
if (instr.is_b_imm) { if (instr.is_b_imm) {
@ -1995,12 +2001,12 @@ private:
// We can't use the constant predicate as destination. // We can't use the constant predicate as destination.
ASSERT(instr.isetp.pred3 != static_cast<u64>(Pred::UnusedIndex)); ASSERT(instr.isetp.pred3 != static_cast<u64>(Pred::UnusedIndex));
std::string second_pred = const std::string second_pred =
GetPredicateCondition(instr.isetp.pred39, instr.isetp.neg_pred != 0); GetPredicateCondition(instr.isetp.pred39, instr.isetp.neg_pred != 0);
std::string combiner = GetPredicateCombiner(instr.isetp.op); const std::string combiner = GetPredicateCombiner(instr.isetp.op);
std::string predicate = GetPredicateComparison(instr.isetp.cond, op_a, op_b); const std::string predicate = GetPredicateComparison(instr.isetp.cond, op_a, op_b);
// Set the primary predicate to the result of Predicate OP SecondPredicate // Set the primary predicate to the result of Predicate OP SecondPredicate
SetPredicate(instr.isetp.pred3, SetPredicate(instr.isetp.pred3,
'(' + predicate + ") " + combiner + " (" + second_pred + ')'); '(' + predicate + ") " + combiner + " (" + second_pred + ')');
@ -2014,20 +2020,20 @@ private:
break; break;
} }
case OpCode::Type::PredicateSetPredicate: { case OpCode::Type::PredicateSetPredicate: {
std::string op_a = const std::string op_a =
GetPredicateCondition(instr.psetp.pred12, instr.psetp.neg_pred12 != 0); GetPredicateCondition(instr.psetp.pred12, instr.psetp.neg_pred12 != 0);
std::string op_b = const std::string op_b =
GetPredicateCondition(instr.psetp.pred29, instr.psetp.neg_pred29 != 0); GetPredicateCondition(instr.psetp.pred29, instr.psetp.neg_pred29 != 0);
// We can't use the constant predicate as destination. // We can't use the constant predicate as destination.
ASSERT(instr.psetp.pred3 != static_cast<u64>(Pred::UnusedIndex)); ASSERT(instr.psetp.pred3 != static_cast<u64>(Pred::UnusedIndex));
std::string second_pred = const std::string second_pred =
GetPredicateCondition(instr.psetp.pred39, instr.psetp.neg_pred39 != 0); GetPredicateCondition(instr.psetp.pred39, instr.psetp.neg_pred39 != 0);
std::string combiner = GetPredicateCombiner(instr.psetp.op); const std::string combiner = GetPredicateCombiner(instr.psetp.op);
std::string predicate = const std::string predicate =
'(' + op_a + ") " + GetPredicateCombiner(instr.psetp.cond) + " (" + op_b + ')'; '(' + op_a + ") " + GetPredicateCombiner(instr.psetp.cond) + " (" + op_b + ')';
// Set the primary predicate to the result of Predicate OP SecondPredicate // Set the primary predicate to the result of Predicate OP SecondPredicate
@ -2053,7 +2059,7 @@ private:
std::string op_b = instr.fset.neg_b ? "-" : ""; std::string op_b = instr.fset.neg_b ? "-" : "";
if (instr.is_b_imm) { if (instr.is_b_imm) {
std::string imm = GetImmediate19(instr); const std::string imm = GetImmediate19(instr);
if (instr.fset.neg_imm) if (instr.fset.neg_imm)
op_b += "(-" + imm + ')'; op_b += "(-" + imm + ')';
else else
@ -2073,12 +2079,13 @@ private:
// The fset instruction sets a register to 1.0 or -1 (depending on the bf bit) if the // The fset instruction sets a register to 1.0 or -1 (depending on the bf bit) if the
// condition is true, and to 0 otherwise. // condition is true, and to 0 otherwise.
std::string second_pred = const std::string second_pred =
GetPredicateCondition(instr.fset.pred39, instr.fset.neg_pred != 0); GetPredicateCondition(instr.fset.pred39, instr.fset.neg_pred != 0);
std::string combiner = GetPredicateCombiner(instr.fset.op); const std::string combiner = GetPredicateCombiner(instr.fset.op);
std::string predicate = "((" + GetPredicateComparison(instr.fset.cond, op_a, op_b) + const std::string predicate = "((" +
GetPredicateComparison(instr.fset.cond, op_a, op_b) +
") " + combiner + " (" + second_pred + "))"; ") " + combiner + " (" + second_pred + "))";
if (instr.fset.bf) { if (instr.fset.bf) {
@ -2090,7 +2097,7 @@ private:
break; break;
} }
case OpCode::Type::IntegerSet: { case OpCode::Type::IntegerSet: {
std::string op_a = regs.GetRegisterAsInteger(instr.gpr8, 0, instr.iset.is_signed); const std::string op_a = regs.GetRegisterAsInteger(instr.gpr8, 0, instr.iset.is_signed);
std::string op_b; std::string op_b;
@ -2107,12 +2114,13 @@ private:
// The iset instruction sets a register to 1.0 or -1 (depending on the bf bit) if the // The iset instruction sets a register to 1.0 or -1 (depending on the bf bit) if the
// condition is true, and to 0 otherwise. // condition is true, and to 0 otherwise.
std::string second_pred = const std::string second_pred =
GetPredicateCondition(instr.iset.pred39, instr.iset.neg_pred != 0); GetPredicateCondition(instr.iset.pred39, instr.iset.neg_pred != 0);
std::string combiner = GetPredicateCombiner(instr.iset.op); const std::string combiner = GetPredicateCombiner(instr.iset.op);
std::string predicate = "((" + GetPredicateComparison(instr.iset.cond, op_a, op_b) + const std::string predicate = "((" +
GetPredicateComparison(instr.iset.cond, op_a, op_b) +
") " + combiner + " (" + second_pred + "))"; ") " + combiner + " (" + second_pred + "))";
if (instr.iset.bf) { if (instr.iset.bf) {
@ -2263,7 +2271,7 @@ private:
case OpCode::Id::BRA: { case OpCode::Id::BRA: {
ASSERT_MSG(instr.bra.constant_buffer == 0, ASSERT_MSG(instr.bra.constant_buffer == 0,
"BRA with constant buffers are not implemented"); "BRA with constant buffers are not implemented");
u32 target = offset + instr.bra.GetBranchTarget(); const u32 target = offset + instr.bra.GetBranchTarget();
shader.AddLine("{ jmp_to = " + std::to_string(target) + "u; break; }"); shader.AddLine("{ jmp_to = " + std::to_string(target) + "u; break; }");
break; break;
} }
@ -2287,7 +2295,7 @@ private:
// has a similar structure to the BRA opcode. // has a similar structure to the BRA opcode.
ASSERT_MSG(instr.bra.constant_buffer == 0, "Constant buffer SSY is not supported"); ASSERT_MSG(instr.bra.constant_buffer == 0, "Constant buffer SSY is not supported");
u32 target = offset + instr.bra.GetBranchTarget(); const u32 target = offset + instr.bra.GetBranchTarget();
EmitPushToSSYStack(target); EmitPushToSSYStack(target);
break; break;
} }
@ -2381,10 +2389,10 @@ private:
shader.AddLine("case " + std::to_string(label) + "u: {"); shader.AddLine("case " + std::to_string(label) + "u: {");
++shader.scope; ++shader.scope;
auto next_it = labels.lower_bound(label + 1); const auto next_it = labels.lower_bound(label + 1);
u32 next_label = next_it == labels.end() ? subroutine.end : *next_it; const u32 next_label = next_it == labels.end() ? subroutine.end : *next_it;
u32 compile_end = CompileRange(label, next_label); const u32 compile_end = CompileRange(label, next_label);
if (compile_end > next_label && compile_end != PROGRAM_END) { if (compile_end > next_label && compile_end != PROGRAM_END) {
// This happens only when there is a label inside a IF/LOOP block // This happens only when there is a label inside a IF/LOOP block
shader.AddLine(" jmp_to = " + std::to_string(compile_end) + "u; break; }"); shader.AddLine(" jmp_to = " + std::to_string(compile_end) + "u; break; }");
@ -2447,7 +2455,8 @@ boost::optional<ProgramResult> DecompileProgram(const ProgramCode& program_code,
Maxwell3D::Regs::ShaderStage stage, Maxwell3D::Regs::ShaderStage stage,
const std::string& suffix) { const std::string& suffix) {
try { try {
auto subroutines = ControlFlowAnalyzer(program_code, main_offset, suffix).GetSubroutines(); const auto subroutines =
ControlFlowAnalyzer(program_code, main_offset, suffix).GetSubroutines();
GLSLGenerator generator(subroutines, program_code, main_offset, stage, suffix); GLSLGenerator generator(subroutines, program_code, main_offset, stage, suffix);
return ProgramResult{generator.GetShaderCode(), generator.GetEntries()}; return ProgramResult{generator.GetShaderCode(), generator.GetEntries()};
} catch (const DecompileFail& exception) { } catch (const DecompileFail& exception) {

@ -25,7 +25,7 @@ GLuint LoadShader(const char* source, GLenum type) {
default: default:
UNREACHABLE(); UNREACHABLE();
} }
GLuint shader_id = glCreateShader(type); const GLuint shader_id = glCreateShader(type);
glShaderSource(shader_id, 1, &source, nullptr); glShaderSource(shader_id, 1, &source, nullptr);
LOG_DEBUG(Render_OpenGL, "Compiling {} shader...", debug_type); LOG_DEBUG(Render_OpenGL, "Compiling {} shader...", debug_type);
glCompileShader(shader_id); glCompileShader(shader_id);

@ -29,7 +29,7 @@ OGLStreamBuffer::OGLStreamBuffer(GLenum target, GLsizeiptr size, bool prefer_coh
if (GLAD_GL_ARB_buffer_storage) { if (GLAD_GL_ARB_buffer_storage) {
persistent = true; persistent = true;
coherent = prefer_coherent; coherent = prefer_coherent;
GLbitfield flags = const GLbitfield flags =
GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | (coherent ? GL_MAP_COHERENT_BIT : 0); GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | (coherent ? GL_MAP_COHERENT_BIT : 0);
glBufferStorage(gl_target, allocate_size, nullptr, flags); glBufferStorage(gl_target, allocate_size, nullptr, flags);
mapped_ptr = static_cast<u8*>(glMapBufferRange( mapped_ptr = static_cast<u8*>(glMapBufferRange(