Merge branch 'master' of https://github.com/yuzu-emu/yuzu
This commit is contained in:
@@ -42,3 +42,7 @@ notifications:
|
|||||||
webhooks:
|
webhooks:
|
||||||
urls:
|
urls:
|
||||||
- https://api.yuzu-emu.org/code/travis/notify
|
- https://api.yuzu-emu.org/code/travis/notify
|
||||||
|
|
||||||
|
cache:
|
||||||
|
directories:
|
||||||
|
- $HOME/.ccache
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
#!/bin/bash -ex
|
#!/bin/bash -ex
|
||||||
|
|
||||||
docker run -v $(pwd):/yuzu ubuntu:18.04 /bin/bash /yuzu/.travis/linux/docker.sh
|
docker run -e CCACHE_DIR=/ccache -v $HOME/.ccache:/ccache -v $(pwd):/yuzu ubuntu:18.04 /bin/bash /yuzu/.travis/linux/docker.sh
|
||||||
|
|||||||
@@ -1,16 +1,18 @@
|
|||||||
#!/bin/bash -ex
|
#!/bin/bash -ex
|
||||||
|
|
||||||
apt-get update
|
apt-get update
|
||||||
apt-get install -y build-essential git libqt5opengl5-dev libsdl2-dev libssl-dev python qtbase5-dev wget ninja-build
|
apt-get install --no-install-recommends -y build-essential git libqt5opengl5-dev libsdl2-dev libssl-dev python qtbase5-dev wget cmake ninja-build ccache
|
||||||
|
|
||||||
# Get a recent version of CMake
|
|
||||||
wget https://cmake.org/files/v3.10/cmake-3.10.1-Linux-x86_64.sh
|
|
||||||
sh cmake-3.10.1-Linux-x86_64.sh --exclude-subdir --prefix=/ --skip-license
|
|
||||||
|
|
||||||
cd /yuzu
|
cd /yuzu
|
||||||
|
|
||||||
|
export PATH=/usr/lib/ccache:$PATH
|
||||||
|
ln -sf /usr/bin/ccache /usr/lib/ccache/cc
|
||||||
|
ln -sf /usr/bin/ccache /usr/lib/ccache/c++
|
||||||
mkdir build && cd build
|
mkdir build && cd build
|
||||||
|
ccache --show-stats > ccache_before
|
||||||
cmake .. -DYUZU_BUILD_UNICORN=ON -DCMAKE_BUILD_TYPE=Release -G Ninja
|
cmake .. -DYUZU_BUILD_UNICORN=ON -DCMAKE_BUILD_TYPE=Release -G Ninja
|
||||||
ninja
|
ninja
|
||||||
|
ccache --show-stats > ccache_after
|
||||||
|
diff -U100 ccache_before ccache_after || true
|
||||||
|
|
||||||
ctest -VV -C Release
|
ctest -VV -C Release
|
||||||
|
|||||||
@@ -7,8 +7,12 @@ export Qt5_DIR=$(brew --prefix)/opt/qt5
|
|||||||
export UNICORNDIR=$(pwd)/externals/unicorn
|
export UNICORNDIR=$(pwd)/externals/unicorn
|
||||||
|
|
||||||
mkdir build && cd build
|
mkdir build && cd build
|
||||||
|
export PATH=/usr/local/opt/ccache/libexec:$PATH
|
||||||
|
ccache --show-stats > ccache_before
|
||||||
cmake --version
|
cmake --version
|
||||||
cmake .. -DYUZU_BUILD_UNICORN=ON -DCMAKE_BUILD_TYPE=Release
|
cmake .. -DYUZU_BUILD_UNICORN=ON -DCMAKE_BUILD_TYPE=Release
|
||||||
make -j4
|
make -j4
|
||||||
|
ccache --show-stats > ccache_after
|
||||||
|
diff -U100 ccache_before ccache_after || true
|
||||||
|
|
||||||
ctest -VV -C Release
|
ctest -VV -C Release
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#!/bin/sh -ex
|
#!/bin/sh -ex
|
||||||
|
|
||||||
brew update
|
brew update
|
||||||
brew install dylibbundler p7zip qt5 sdl2
|
brew install dylibbundler p7zip qt5 sdl2 ccache
|
||||||
brew outdated cmake || brew upgrade cmake
|
brew outdated cmake || brew upgrade cmake
|
||||||
|
|||||||
@@ -64,6 +64,10 @@ std::string ArrayToString(const u8* data, size_t size, int line_len, bool spaces
|
|||||||
return oss.str();
|
return oss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string StringFromBuffer(const std::vector<u8>& data) {
|
||||||
|
return std::string(data.begin(), std::find(data.begin(), data.end(), '\0'));
|
||||||
|
}
|
||||||
|
|
||||||
// Turns " hej " into "hej". Also handles tabs.
|
// Turns " hej " into "hej". Also handles tabs.
|
||||||
std::string StripSpaces(const std::string& str) {
|
std::string StripSpaces(const std::string& str) {
|
||||||
const size_t s = str.find_first_not_of(" \t\r\n");
|
const size_t s = str.find_first_not_of(" \t\r\n");
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ std::string ToUpper(std::string str);
|
|||||||
|
|
||||||
std::string ArrayToString(const u8* data, size_t size, int line_len = 20, bool spaces = true);
|
std::string ArrayToString(const u8* data, size_t size, int line_len = 20, bool spaces = true);
|
||||||
|
|
||||||
|
std::string StringFromBuffer(const std::vector<u8>& data);
|
||||||
|
|
||||||
std::string StripSpaces(const std::string& s);
|
std::string StripSpaces(const std::string& s);
|
||||||
std::string StripQuotes(const std::string& s);
|
std::string StripQuotes(const std::string& s);
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#include <cinttypes>
|
#include <cinttypes>
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
|
#include "common/string_util.h"
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
#include "core/file_sys/directory.h"
|
#include "core/file_sys/directory.h"
|
||||||
#include "core/file_sys/filesystem.h"
|
#include "core/file_sys/filesystem.h"
|
||||||
@@ -258,9 +259,7 @@ public:
|
|||||||
IPC::RequestParser rp{ctx};
|
IPC::RequestParser rp{ctx};
|
||||||
|
|
||||||
auto file_buffer = ctx.ReadBuffer();
|
auto file_buffer = ctx.ReadBuffer();
|
||||||
auto end = std::find(file_buffer.begin(), file_buffer.end(), '\0');
|
std::string name = Common::StringFromBuffer(file_buffer);
|
||||||
|
|
||||||
std::string name(file_buffer.begin(), end);
|
|
||||||
|
|
||||||
u64 mode = rp.Pop<u64>();
|
u64 mode = rp.Pop<u64>();
|
||||||
u32 size = rp.Pop<u32>();
|
u32 size = rp.Pop<u32>();
|
||||||
@@ -275,9 +274,7 @@ public:
|
|||||||
IPC::RequestParser rp{ctx};
|
IPC::RequestParser rp{ctx};
|
||||||
|
|
||||||
auto file_buffer = ctx.ReadBuffer();
|
auto file_buffer = ctx.ReadBuffer();
|
||||||
auto end = std::find(file_buffer.begin(), file_buffer.end(), '\0');
|
std::string name = Common::StringFromBuffer(file_buffer);
|
||||||
|
|
||||||
std::string name(file_buffer.begin(), end);
|
|
||||||
|
|
||||||
NGLOG_DEBUG(Service_FS, "called file {}", name);
|
NGLOG_DEBUG(Service_FS, "called file {}", name);
|
||||||
|
|
||||||
@@ -289,9 +286,7 @@ public:
|
|||||||
IPC::RequestParser rp{ctx};
|
IPC::RequestParser rp{ctx};
|
||||||
|
|
||||||
auto file_buffer = ctx.ReadBuffer();
|
auto file_buffer = ctx.ReadBuffer();
|
||||||
auto end = std::find(file_buffer.begin(), file_buffer.end(), '\0');
|
std::string name = Common::StringFromBuffer(file_buffer);
|
||||||
|
|
||||||
std::string name(file_buffer.begin(), end);
|
|
||||||
|
|
||||||
NGLOG_DEBUG(Service_FS, "called directory {}", name);
|
NGLOG_DEBUG(Service_FS, "called directory {}", name);
|
||||||
|
|
||||||
@@ -305,13 +300,11 @@ public:
|
|||||||
std::vector<u8> buffer;
|
std::vector<u8> buffer;
|
||||||
buffer.resize(ctx.BufferDescriptorX()[0].Size());
|
buffer.resize(ctx.BufferDescriptorX()[0].Size());
|
||||||
Memory::ReadBlock(ctx.BufferDescriptorX()[0].Address(), buffer.data(), buffer.size());
|
Memory::ReadBlock(ctx.BufferDescriptorX()[0].Address(), buffer.data(), buffer.size());
|
||||||
auto end = std::find(buffer.begin(), buffer.end(), '\0');
|
std::string src_name = Common::StringFromBuffer(buffer);
|
||||||
std::string src_name(buffer.begin(), end);
|
|
||||||
|
|
||||||
buffer.resize(ctx.BufferDescriptorX()[1].Size());
|
buffer.resize(ctx.BufferDescriptorX()[1].Size());
|
||||||
Memory::ReadBlock(ctx.BufferDescriptorX()[1].Address(), buffer.data(), buffer.size());
|
Memory::ReadBlock(ctx.BufferDescriptorX()[1].Address(), buffer.data(), buffer.size());
|
||||||
end = std::find(buffer.begin(), buffer.end(), '\0');
|
std::string dst_name = Common::StringFromBuffer(buffer);
|
||||||
std::string dst_name(buffer.begin(), end);
|
|
||||||
|
|
||||||
NGLOG_DEBUG(Service_FS, "called file '{}' to file '{}'", src_name, dst_name);
|
NGLOG_DEBUG(Service_FS, "called file '{}' to file '{}'", src_name, dst_name);
|
||||||
|
|
||||||
@@ -323,9 +316,7 @@ public:
|
|||||||
IPC::RequestParser rp{ctx};
|
IPC::RequestParser rp{ctx};
|
||||||
|
|
||||||
auto file_buffer = ctx.ReadBuffer();
|
auto file_buffer = ctx.ReadBuffer();
|
||||||
auto end = std::find(file_buffer.begin(), file_buffer.end(), '\0');
|
std::string name = Common::StringFromBuffer(file_buffer);
|
||||||
|
|
||||||
std::string name(file_buffer.begin(), end);
|
|
||||||
|
|
||||||
auto mode = static_cast<FileSys::Mode>(rp.Pop<u32>());
|
auto mode = static_cast<FileSys::Mode>(rp.Pop<u32>());
|
||||||
|
|
||||||
@@ -349,9 +340,7 @@ public:
|
|||||||
IPC::RequestParser rp{ctx};
|
IPC::RequestParser rp{ctx};
|
||||||
|
|
||||||
auto file_buffer = ctx.ReadBuffer();
|
auto file_buffer = ctx.ReadBuffer();
|
||||||
auto end = std::find(file_buffer.begin(), file_buffer.end(), '\0');
|
std::string name = Common::StringFromBuffer(file_buffer);
|
||||||
|
|
||||||
std::string name(file_buffer.begin(), end);
|
|
||||||
|
|
||||||
// TODO(Subv): Implement this filter.
|
// TODO(Subv): Implement this filter.
|
||||||
u32 filter_flags = rp.Pop<u32>();
|
u32 filter_flags = rp.Pop<u32>();
|
||||||
@@ -376,9 +365,7 @@ public:
|
|||||||
IPC::RequestParser rp{ctx};
|
IPC::RequestParser rp{ctx};
|
||||||
|
|
||||||
auto file_buffer = ctx.ReadBuffer();
|
auto file_buffer = ctx.ReadBuffer();
|
||||||
auto end = std::find(file_buffer.begin(), file_buffer.end(), '\0');
|
std::string name = Common::StringFromBuffer(file_buffer);
|
||||||
|
|
||||||
std::string name(file_buffer.begin(), end);
|
|
||||||
|
|
||||||
NGLOG_DEBUG(Service_FS, "called file {}", name);
|
NGLOG_DEBUG(Service_FS, "called file {}", name);
|
||||||
|
|
||||||
|
|||||||
@@ -318,6 +318,7 @@ public:
|
|||||||
Equation equation_a;
|
Equation equation_a;
|
||||||
Factor factor_source_a;
|
Factor factor_source_a;
|
||||||
Factor factor_dest_a;
|
Factor factor_dest_a;
|
||||||
|
INSERT_PADDING_WORDS(1);
|
||||||
};
|
};
|
||||||
|
|
||||||
union {
|
union {
|
||||||
@@ -432,7 +433,27 @@ public:
|
|||||||
};
|
};
|
||||||
} rt_control;
|
} rt_control;
|
||||||
|
|
||||||
INSERT_PADDING_WORDS(0xCF);
|
INSERT_PADDING_WORDS(0x31);
|
||||||
|
|
||||||
|
u32 independent_blend_enable;
|
||||||
|
|
||||||
|
INSERT_PADDING_WORDS(0x15);
|
||||||
|
|
||||||
|
struct {
|
||||||
|
u32 separate_alpha;
|
||||||
|
Blend::Equation equation_rgb;
|
||||||
|
Blend::Factor factor_source_rgb;
|
||||||
|
Blend::Factor factor_dest_rgb;
|
||||||
|
Blend::Equation equation_a;
|
||||||
|
Blend::Factor factor_source_a;
|
||||||
|
INSERT_PADDING_WORDS(1);
|
||||||
|
Blend::Factor factor_dest_a;
|
||||||
|
|
||||||
|
u32 enable_common;
|
||||||
|
u32 enable[NumRenderTargets];
|
||||||
|
} blend;
|
||||||
|
|
||||||
|
INSERT_PADDING_WORDS(0x77);
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
u32 tsc_address_high;
|
u32 tsc_address_high;
|
||||||
@@ -557,9 +578,7 @@ public:
|
|||||||
|
|
||||||
} vertex_array[NumVertexArrays];
|
} vertex_array[NumVertexArrays];
|
||||||
|
|
||||||
Blend blend;
|
Blend independent_blend[NumRenderTargets];
|
||||||
|
|
||||||
INSERT_PADDING_WORDS(0x39);
|
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
u32 limit_high;
|
u32 limit_high;
|
||||||
@@ -722,6 +741,8 @@ ASSERT_REG_POSITION(vertex_buffer, 0x35D);
|
|||||||
ASSERT_REG_POSITION(zeta, 0x3F8);
|
ASSERT_REG_POSITION(zeta, 0x3F8);
|
||||||
ASSERT_REG_POSITION(vertex_attrib_format[0], 0x458);
|
ASSERT_REG_POSITION(vertex_attrib_format[0], 0x458);
|
||||||
ASSERT_REG_POSITION(rt_control, 0x487);
|
ASSERT_REG_POSITION(rt_control, 0x487);
|
||||||
|
ASSERT_REG_POSITION(independent_blend_enable, 0x4B9);
|
||||||
|
ASSERT_REG_POSITION(blend, 0x4CF);
|
||||||
ASSERT_REG_POSITION(tsc, 0x557);
|
ASSERT_REG_POSITION(tsc, 0x557);
|
||||||
ASSERT_REG_POSITION(tic, 0x55D);
|
ASSERT_REG_POSITION(tic, 0x55D);
|
||||||
ASSERT_REG_POSITION(code_address, 0x582);
|
ASSERT_REG_POSITION(code_address, 0x582);
|
||||||
@@ -729,7 +750,7 @@ ASSERT_REG_POSITION(draw, 0x585);
|
|||||||
ASSERT_REG_POSITION(index_array, 0x5F2);
|
ASSERT_REG_POSITION(index_array, 0x5F2);
|
||||||
ASSERT_REG_POSITION(query, 0x6C0);
|
ASSERT_REG_POSITION(query, 0x6C0);
|
||||||
ASSERT_REG_POSITION(vertex_array[0], 0x700);
|
ASSERT_REG_POSITION(vertex_array[0], 0x700);
|
||||||
ASSERT_REG_POSITION(blend, 0x780);
|
ASSERT_REG_POSITION(independent_blend, 0x780);
|
||||||
ASSERT_REG_POSITION(vertex_array_limit[0], 0x7C0);
|
ASSERT_REG_POSITION(vertex_array_limit[0], 0x7C0);
|
||||||
ASSERT_REG_POSITION(shader_config[0], 0x800);
|
ASSERT_REG_POSITION(shader_config[0], 0x800);
|
||||||
ASSERT_REG_POSITION(const_buffer, 0x8E0);
|
ASSERT_REG_POSITION(const_buffer, 0x8E0);
|
||||||
|
|||||||
@@ -213,6 +213,7 @@ union Instruction {
|
|||||||
BitField<28, 8, Register> gpr28;
|
BitField<28, 8, Register> gpr28;
|
||||||
BitField<39, 8, Register> gpr39;
|
BitField<39, 8, Register> gpr39;
|
||||||
BitField<48, 16, u64> opcode;
|
BitField<48, 16, u64> opcode;
|
||||||
|
BitField<50, 1, u64> saturate_a;
|
||||||
|
|
||||||
union {
|
union {
|
||||||
BitField<20, 19, u64> imm20_19;
|
BitField<20, 19, u64> imm20_19;
|
||||||
@@ -259,11 +260,15 @@ union Instruction {
|
|||||||
}
|
}
|
||||||
} alu;
|
} alu;
|
||||||
|
|
||||||
|
union {
|
||||||
|
BitField<48, 1, u64> is_signed;
|
||||||
|
} shift;
|
||||||
|
|
||||||
union {
|
union {
|
||||||
BitField<39, 5, u64> shift_amount;
|
BitField<39, 5, u64> shift_amount;
|
||||||
BitField<48, 1, u64> negate_b;
|
BitField<48, 1, u64> negate_b;
|
||||||
BitField<49, 1, u64> negate_a;
|
BitField<49, 1, u64> negate_a;
|
||||||
} iscadd;
|
} alu_integer;
|
||||||
|
|
||||||
union {
|
union {
|
||||||
BitField<20, 8, u64> shift_position;
|
BitField<20, 8, u64> shift_position;
|
||||||
@@ -331,7 +336,6 @@ union Instruction {
|
|||||||
BitField<41, 2, u64> selector;
|
BitField<41, 2, u64> selector;
|
||||||
BitField<45, 1, u64> negate_a;
|
BitField<45, 1, u64> negate_a;
|
||||||
BitField<49, 1, u64> abs_a;
|
BitField<49, 1, u64> abs_a;
|
||||||
BitField<50, 1, u64> saturate_a;
|
|
||||||
|
|
||||||
union {
|
union {
|
||||||
BitField<39, 2, F2iRoundingOp> rounding;
|
BitField<39, 2, F2iRoundingOp> rounding;
|
||||||
@@ -410,6 +414,7 @@ class OpCode {
|
|||||||
public:
|
public:
|
||||||
enum class Id {
|
enum class Id {
|
||||||
KIL,
|
KIL,
|
||||||
|
SSY,
|
||||||
BFE_C,
|
BFE_C,
|
||||||
BFE_R,
|
BFE_R,
|
||||||
BFE_IMM,
|
BFE_IMM,
|
||||||
@@ -434,6 +439,9 @@ public:
|
|||||||
FMUL_R,
|
FMUL_R,
|
||||||
FMUL_IMM,
|
FMUL_IMM,
|
||||||
FMUL32_IMM,
|
FMUL32_IMM,
|
||||||
|
IADD_C,
|
||||||
|
IADD_R,
|
||||||
|
IADD_IMM,
|
||||||
ISCADD_C, // Scale and Add
|
ISCADD_C, // Scale and Add
|
||||||
ISCADD_R,
|
ISCADD_R,
|
||||||
ISCADD_IMM,
|
ISCADD_IMM,
|
||||||
@@ -489,10 +497,10 @@ public:
|
|||||||
enum class Type {
|
enum class Type {
|
||||||
Trivial,
|
Trivial,
|
||||||
Arithmetic,
|
Arithmetic,
|
||||||
|
ArithmeticInteger,
|
||||||
Bfe,
|
Bfe,
|
||||||
Logic,
|
Logic,
|
||||||
Shift,
|
Shift,
|
||||||
ScaledAdd,
|
|
||||||
Ffma,
|
Ffma,
|
||||||
Flow,
|
Flow,
|
||||||
Memory,
|
Memory,
|
||||||
@@ -596,6 +604,7 @@ private:
|
|||||||
std::vector<Matcher> table = {
|
std::vector<Matcher> table = {
|
||||||
#define INST(bitstring, op, type, name) Detail::GetMatcher(bitstring, op, type, name)
|
#define INST(bitstring, op, type, name) Detail::GetMatcher(bitstring, op, type, name)
|
||||||
INST("111000110011----", Id::KIL, Type::Flow, "KIL"),
|
INST("111000110011----", Id::KIL, Type::Flow, "KIL"),
|
||||||
|
INST("111000101001----", Id::SSY, Type::Flow, "SSY"),
|
||||||
INST("111000100100----", Id::BRA, Type::Flow, "BRA"),
|
INST("111000100100----", Id::BRA, Type::Flow, "BRA"),
|
||||||
INST("1110111111011---", Id::LD_A, Type::Memory, "LD_A"),
|
INST("1110111111011---", Id::LD_A, Type::Memory, "LD_A"),
|
||||||
INST("1110111110010---", Id::LD_C, Type::Memory, "LD_C"),
|
INST("1110111110010---", Id::LD_C, Type::Memory, "LD_C"),
|
||||||
@@ -617,9 +626,12 @@ private:
|
|||||||
INST("0101110001101---", Id::FMUL_R, Type::Arithmetic, "FMUL_R"),
|
INST("0101110001101---", Id::FMUL_R, Type::Arithmetic, "FMUL_R"),
|
||||||
INST("0011100-01101---", Id::FMUL_IMM, Type::Arithmetic, "FMUL_IMM"),
|
INST("0011100-01101---", Id::FMUL_IMM, Type::Arithmetic, "FMUL_IMM"),
|
||||||
INST("00011110--------", Id::FMUL32_IMM, Type::Arithmetic, "FMUL32_IMM"),
|
INST("00011110--------", Id::FMUL32_IMM, Type::Arithmetic, "FMUL32_IMM"),
|
||||||
INST("0100110000011---", Id::ISCADD_C, Type::ScaledAdd, "ISCADD_C"),
|
INST("0100110000010---", Id::IADD_C, Type::ArithmeticInteger, "IADD_C"),
|
||||||
INST("0101110000011---", Id::ISCADD_R, Type::ScaledAdd, "ISCADD_R"),
|
INST("0101110000010---", Id::IADD_R, Type::ArithmeticInteger, "IADD_R"),
|
||||||
INST("0011100-00011---", Id::ISCADD_IMM, Type::ScaledAdd, "ISCADD_IMM"),
|
INST("0011100-00010---", Id::IADD_IMM, Type::ArithmeticInteger, "IADD_IMM"),
|
||||||
|
INST("0100110000011---", Id::ISCADD_C, Type::ArithmeticInteger, "ISCADD_C"),
|
||||||
|
INST("0101110000011---", Id::ISCADD_R, Type::ArithmeticInteger, "ISCADD_R"),
|
||||||
|
INST("0011100-00011---", Id::ISCADD_IMM, Type::ArithmeticInteger, "ISCADD_IMM"),
|
||||||
INST("0101000010000---", Id::MUFU, Type::Arithmetic, "MUFU"),
|
INST("0101000010000---", Id::MUFU, Type::Arithmetic, "MUFU"),
|
||||||
INST("0100110010010---", Id::RRO_C, Type::Arithmetic, "RRO_C"),
|
INST("0100110010010---", Id::RRO_C, Type::Arithmetic, "RRO_C"),
|
||||||
INST("0101110010010---", Id::RRO_R, Type::Arithmetic, "RRO_R"),
|
INST("0101110010010---", Id::RRO_R, Type::Arithmetic, "RRO_R"),
|
||||||
|
|||||||
@@ -218,6 +218,9 @@ void RasterizerOpenGL::SetupShaders(u8* buffer_ptr, GLintptr buffer_offset) {
|
|||||||
ubo.SetFromRegs(gpu.state.shader_stages[stage]);
|
ubo.SetFromRegs(gpu.state.shader_stages[stage]);
|
||||||
std::memcpy(buffer_ptr, &ubo, sizeof(ubo));
|
std::memcpy(buffer_ptr, &ubo, sizeof(ubo));
|
||||||
|
|
||||||
|
// Flush the buffer so that the GPU can see the data we just wrote.
|
||||||
|
glFlushMappedBufferRange(GL_ARRAY_BUFFER, buffer_offset, sizeof(ubo));
|
||||||
|
|
||||||
// Upload uniform data as one UBO per stage
|
// Upload uniform data as one UBO per stage
|
||||||
const GLintptr ubo_offset = buffer_offset;
|
const GLintptr ubo_offset = buffer_offset;
|
||||||
copy_buffer(uniform_buffers[stage].handle, ubo_offset,
|
copy_buffer(uniform_buffers[stage].handle, ubo_offset,
|
||||||
@@ -346,6 +349,9 @@ void RasterizerOpenGL::DrawArrays() {
|
|||||||
// Sync the viewport
|
// Sync the viewport
|
||||||
SyncViewport(surfaces_rect, res_scale);
|
SyncViewport(surfaces_rect, res_scale);
|
||||||
|
|
||||||
|
// Sync the blend state registers
|
||||||
|
SyncBlendState();
|
||||||
|
|
||||||
// TODO(bunnei): Sync framebuffer_scale uniform here
|
// TODO(bunnei): Sync framebuffer_scale uniform here
|
||||||
// TODO(bunnei): Sync scissorbox uniform(s) here
|
// TODO(bunnei): Sync scissorbox uniform(s) here
|
||||||
|
|
||||||
@@ -452,32 +458,7 @@ void RasterizerOpenGL::DrawArrays() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerOpenGL::NotifyMaxwellRegisterChanged(u32 method) {
|
void RasterizerOpenGL::NotifyMaxwellRegisterChanged(u32 method) {}
|
||||||
const auto& regs = Core::System().GetInstance().GPU().Maxwell3D().regs;
|
|
||||||
switch (method) {
|
|
||||||
case MAXWELL3D_REG_INDEX(blend.separate_alpha):
|
|
||||||
ASSERT_MSG(false, "unimplemented");
|
|
||||||
break;
|
|
||||||
case MAXWELL3D_REG_INDEX(blend.equation_rgb):
|
|
||||||
state.blend.rgb_equation = MaxwellToGL::BlendEquation(regs.blend.equation_rgb);
|
|
||||||
break;
|
|
||||||
case MAXWELL3D_REG_INDEX(blend.factor_source_rgb):
|
|
||||||
state.blend.src_rgb_func = MaxwellToGL::BlendFunc(regs.blend.factor_source_rgb);
|
|
||||||
break;
|
|
||||||
case MAXWELL3D_REG_INDEX(blend.factor_dest_rgb):
|
|
||||||
state.blend.dst_rgb_func = MaxwellToGL::BlendFunc(regs.blend.factor_dest_rgb);
|
|
||||||
break;
|
|
||||||
case MAXWELL3D_REG_INDEX(blend.equation_a):
|
|
||||||
state.blend.a_equation = MaxwellToGL::BlendEquation(regs.blend.equation_a);
|
|
||||||
break;
|
|
||||||
case MAXWELL3D_REG_INDEX(blend.factor_source_a):
|
|
||||||
state.blend.src_a_func = MaxwellToGL::BlendFunc(regs.blend.factor_source_a);
|
|
||||||
break;
|
|
||||||
case MAXWELL3D_REG_INDEX(blend.factor_dest_a):
|
|
||||||
state.blend.dst_a_func = MaxwellToGL::BlendFunc(regs.blend.factor_dest_a);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void RasterizerOpenGL::FlushAll() {
|
void RasterizerOpenGL::FlushAll() {
|
||||||
MICROPROFILE_SCOPE(OpenGL_CacheManagement);
|
MICROPROFILE_SCOPE(OpenGL_CacheManagement);
|
||||||
@@ -757,14 +738,21 @@ void RasterizerOpenGL::SyncDepthOffset() {
|
|||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerOpenGL::SyncBlendEnabled() {
|
void RasterizerOpenGL::SyncBlendState() {
|
||||||
UNREACHABLE();
|
const auto& regs = Core::System().GetInstance().GPU().Maxwell3D().regs;
|
||||||
}
|
ASSERT_MSG(regs.independent_blend_enable == 1, "Only independent blending is implemented");
|
||||||
|
|
||||||
void RasterizerOpenGL::SyncBlendFuncs() {
|
// TODO(Subv): Support more than just render target 0.
|
||||||
UNREACHABLE();
|
state.blend.enabled = regs.blend.enable[0] != 0;
|
||||||
}
|
|
||||||
|
|
||||||
void RasterizerOpenGL::SyncBlendColor() {
|
if (!state.blend.enabled)
|
||||||
UNREACHABLE();
|
return;
|
||||||
|
|
||||||
|
ASSERT_MSG(!regs.independent_blend[0].separate_alpha, "Unimplemented");
|
||||||
|
state.blend.rgb_equation = MaxwellToGL::BlendEquation(regs.independent_blend[0].equation_rgb);
|
||||||
|
state.blend.src_rgb_func = MaxwellToGL::BlendFunc(regs.independent_blend[0].factor_source_rgb);
|
||||||
|
state.blend.dst_rgb_func = MaxwellToGL::BlendFunc(regs.independent_blend[0].factor_dest_rgb);
|
||||||
|
state.blend.a_equation = MaxwellToGL::BlendEquation(regs.independent_blend[0].equation_a);
|
||||||
|
state.blend.src_a_func = MaxwellToGL::BlendFunc(regs.independent_blend[0].factor_source_a);
|
||||||
|
state.blend.dst_a_func = MaxwellToGL::BlendFunc(regs.independent_blend[0].factor_dest_a);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -121,14 +121,8 @@ private:
|
|||||||
/// Syncs the depth offset to match the guest state
|
/// Syncs the depth offset to match the guest state
|
||||||
void SyncDepthOffset();
|
void SyncDepthOffset();
|
||||||
|
|
||||||
/// Syncs the blend enabled status to match the guest state
|
/// Syncs the blend state to match the guest state
|
||||||
void SyncBlendEnabled();
|
void SyncBlendState();
|
||||||
|
|
||||||
/// Syncs the blend functions to match the guest state
|
|
||||||
void SyncBlendFuncs();
|
|
||||||
|
|
||||||
/// Syncs the blend color to match the guest state
|
|
||||||
void SyncBlendColor();
|
|
||||||
|
|
||||||
bool has_ARB_buffer_storage;
|
bool has_ARB_buffer_storage;
|
||||||
bool has_ARB_direct_state_access;
|
bool has_ARB_direct_state_access;
|
||||||
|
|||||||
@@ -1033,8 +1033,11 @@ Surface RasterizerCacheOpenGL::GetTextureSurface(const Tegra::Texture::FullTextu
|
|||||||
params.addr = config.tic.Address();
|
params.addr = config.tic.Address();
|
||||||
params.is_tiled = config.tic.IsTiled();
|
params.is_tiled = config.tic.IsTiled();
|
||||||
params.pixel_format = SurfaceParams::PixelFormatFromTextureFormat(config.tic.format);
|
params.pixel_format = SurfaceParams::PixelFormatFromTextureFormat(config.tic.format);
|
||||||
params.width = config.tic.Width() / params.GetCompresssionFactor();
|
|
||||||
params.height = config.tic.Height() / params.GetCompresssionFactor();
|
params.width = Common::AlignUp(config.tic.Width(), params.GetCompresssionFactor()) /
|
||||||
|
params.GetCompresssionFactor();
|
||||||
|
params.height = Common::AlignUp(config.tic.Height(), params.GetCompresssionFactor()) /
|
||||||
|
params.GetCompresssionFactor();
|
||||||
|
|
||||||
// TODO(Subv): Different types per component are not supported.
|
// TODO(Subv): Different types per component are not supported.
|
||||||
ASSERT(config.tic.r_type.Value() == config.tic.g_type.Value() &&
|
ASSERT(config.tic.r_type.Value() == config.tic.g_type.Value() &&
|
||||||
@@ -1045,6 +1048,8 @@ Surface RasterizerCacheOpenGL::GetTextureSurface(const Tegra::Texture::FullTextu
|
|||||||
|
|
||||||
if (config.tic.IsTiled()) {
|
if (config.tic.IsTiled()) {
|
||||||
params.block_height = config.tic.BlockHeight();
|
params.block_height = config.tic.BlockHeight();
|
||||||
|
params.width = Common::AlignUp(params.width, params.block_height);
|
||||||
|
params.height = Common::AlignUp(params.height, params.block_height);
|
||||||
} else {
|
} else {
|
||||||
// Use the texture-provided stride value if the texture isn't tiled.
|
// Use the texture-provided stride value if the texture isn't tiled.
|
||||||
params.stride = static_cast<u32>(params.PixelsInBytes(config.tic.Pitch()));
|
params.stride = static_cast<u32>(params.PixelsInBytes(config.tic.Pitch()));
|
||||||
|
|||||||
@@ -808,6 +808,8 @@ private:
|
|||||||
case OpCode::Id::FMUL_C:
|
case OpCode::Id::FMUL_C:
|
||||||
case OpCode::Id::FMUL_R:
|
case OpCode::Id::FMUL_R:
|
||||||
case OpCode::Id::FMUL_IMM: {
|
case OpCode::Id::FMUL_IMM: {
|
||||||
|
ASSERT_MSG(!instr.saturate_a, "Unimplemented");
|
||||||
|
|
||||||
regs.SetRegisterToFloat(instr.gpr0, 0, op_a + " * " + op_b, 1, 1, instr.alu.abs_d);
|
regs.SetRegisterToFloat(instr.gpr0, 0, op_a + " * " + op_b, 1, 1, instr.alu.abs_d);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -821,10 +823,14 @@ private:
|
|||||||
case OpCode::Id::FADD_C:
|
case OpCode::Id::FADD_C:
|
||||||
case OpCode::Id::FADD_R:
|
case OpCode::Id::FADD_R:
|
||||||
case OpCode::Id::FADD_IMM: {
|
case OpCode::Id::FADD_IMM: {
|
||||||
|
ASSERT_MSG(!instr.saturate_a, "Unimplemented");
|
||||||
|
|
||||||
regs.SetRegisterToFloat(instr.gpr0, 0, op_a + " + " + op_b, 1, 1, instr.alu.abs_d);
|
regs.SetRegisterToFloat(instr.gpr0, 0, op_a + " + " + op_b, 1, 1, instr.alu.abs_d);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case OpCode::Id::MUFU: {
|
case OpCode::Id::MUFU: {
|
||||||
|
ASSERT_MSG(!instr.saturate_a, "Unimplemented");
|
||||||
|
|
||||||
switch (instr.sub_op) {
|
switch (instr.sub_op) {
|
||||||
case SubOp::Cos:
|
case SubOp::Cos:
|
||||||
regs.SetRegisterToFloat(instr.gpr0, 0, "cos(" + op_a + ')', 1, 1,
|
regs.SetRegisterToFloat(instr.gpr0, 0, "cos(" + op_a + ')', 1, 1,
|
||||||
@@ -973,6 +979,19 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch (opcode->GetId()) {
|
switch (opcode->GetId()) {
|
||||||
|
case OpCode::Id::SHR_C:
|
||||||
|
case OpCode::Id::SHR_R:
|
||||||
|
case OpCode::Id::SHR_IMM: {
|
||||||
|
if (!instr.shift.is_signed) {
|
||||||
|
// Logical shift right
|
||||||
|
op_a = "uint(" + op_a + ')';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cast to int is superfluous for arithmetic shift, it's only for a logical shift
|
||||||
|
regs.SetRegisterToInteger(instr.gpr0, true, 0, "int(" + op_a + " >> " + op_b + ')',
|
||||||
|
1, 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case OpCode::Id::SHL_C:
|
case OpCode::Id::SHL_C:
|
||||||
case OpCode::Id::SHL_R:
|
case OpCode::Id::SHL_R:
|
||||||
case OpCode::Id::SHL_IMM:
|
case OpCode::Id::SHL_IMM:
|
||||||
@@ -986,13 +1005,13 @@ private:
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case OpCode::Type::ScaledAdd: {
|
case OpCode::Type::ArithmeticInteger: {
|
||||||
std::string op_a = regs.GetRegisterAsInteger(instr.gpr8);
|
std::string op_a = regs.GetRegisterAsInteger(instr.gpr8);
|
||||||
|
|
||||||
if (instr.iscadd.negate_a)
|
if (instr.alu_integer.negate_a)
|
||||||
op_a = '-' + op_a;
|
op_a = '-' + op_a;
|
||||||
|
|
||||||
std::string op_b = instr.iscadd.negate_b ? "-" : "";
|
std::string op_b = instr.alu_integer.negate_b ? "-" : "";
|
||||||
|
|
||||||
if (instr.is_b_imm) {
|
if (instr.is_b_imm) {
|
||||||
op_b += '(' + std::to_string(instr.alu.GetSignedImm20_20()) + ')';
|
op_b += '(' + std::to_string(instr.alu.GetSignedImm20_20()) + ')';
|
||||||
@@ -1005,13 +1024,35 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string shift = std::to_string(instr.iscadd.shift_amount.Value());
|
switch (opcode->GetId()) {
|
||||||
|
case OpCode::Id::IADD_C:
|
||||||
|
case OpCode::Id::IADD_R:
|
||||||
|
case OpCode::Id::IADD_IMM: {
|
||||||
|
ASSERT_MSG(!instr.saturate_a, "Unimplemented");
|
||||||
|
regs.SetRegisterToInteger(instr.gpr0, true, 0, op_a + " + " + op_b, 1, 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OpCode::Id::ISCADD_C:
|
||||||
|
case OpCode::Id::ISCADD_R:
|
||||||
|
case OpCode::Id::ISCADD_IMM: {
|
||||||
|
std::string shift = std::to_string(instr.alu_integer.shift_amount.Value());
|
||||||
|
|
||||||
|
regs.SetRegisterToInteger(instr.gpr0, true, 0,
|
||||||
|
"((" + op_a + " << " + shift + ") + " + op_b + ')', 1, 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
NGLOG_CRITICAL(HW_GPU, "Unhandled ArithmeticInteger instruction: {}",
|
||||||
|
opcode->GetName());
|
||||||
|
UNREACHABLE();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
regs.SetRegisterToInteger(instr.gpr0, true, 0,
|
|
||||||
"((" + op_a + " << " + shift + ") + " + op_b + ')', 1, 1);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case OpCode::Type::Ffma: {
|
case OpCode::Type::Ffma: {
|
||||||
|
ASSERT_MSG(!instr.saturate_a, "Unimplemented");
|
||||||
|
|
||||||
std::string op_a = regs.GetRegisterAsFloat(instr.gpr8);
|
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 ? "-" : "";
|
||||||
@@ -1051,7 +1092,7 @@ private:
|
|||||||
case OpCode::Type::Conversion: {
|
case OpCode::Type::Conversion: {
|
||||||
ASSERT_MSG(instr.conversion.size == Register::Size::Word, "Unimplemented");
|
ASSERT_MSG(instr.conversion.size == Register::Size::Word, "Unimplemented");
|
||||||
ASSERT_MSG(!instr.conversion.negate_a, "Unimplemented");
|
ASSERT_MSG(!instr.conversion.negate_a, "Unimplemented");
|
||||||
ASSERT_MSG(!instr.conversion.saturate_a, "Unimplemented");
|
ASSERT_MSG(!instr.saturate_a, "Unimplemented");
|
||||||
|
|
||||||
switch (opcode->GetId()) {
|
switch (opcode->GetId()) {
|
||||||
case OpCode::Id::I2I_R: {
|
case OpCode::Id::I2I_R: {
|
||||||
@@ -1081,6 +1122,8 @@ private:
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case OpCode::Id::F2F_R: {
|
case OpCode::Id::F2F_R: {
|
||||||
|
ASSERT_MSG(!instr.saturate_a, "Unimplemented");
|
||||||
|
|
||||||
std::string op_a = regs.GetRegisterAsFloat(instr.gpr20);
|
std::string op_a = regs.GetRegisterAsFloat(instr.gpr20);
|
||||||
|
|
||||||
switch (instr.conversion.f2f.rounding) {
|
switch (instr.conversion.f2f.rounding) {
|
||||||
@@ -1198,8 +1241,8 @@ private:
|
|||||||
const std::string op_b = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1);
|
const std::string op_b = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1);
|
||||||
const std::string sampler = GetSampler(instr.sampler);
|
const std::string sampler = GetSampler(instr.sampler);
|
||||||
const std::string coord = "vec2 coords = vec2(" + op_a + ", " + op_b + ");";
|
const std::string coord = "vec2 coords = vec2(" + op_a + ", " + op_b + ");";
|
||||||
// Add an extra scope and declare the texture coords inside to prevent overwriting
|
// Add an extra scope and declare the texture coords inside to prevent
|
||||||
// them in case they are used as outputs of the texs instruction.
|
// overwriting them in case they are used as outputs of the texs instruction.
|
||||||
shader.AddLine("{");
|
shader.AddLine("{");
|
||||||
++shader.scope;
|
++shader.scope;
|
||||||
shader.AddLine(coord);
|
shader.AddLine(coord);
|
||||||
@@ -1230,8 +1273,8 @@ private:
|
|||||||
shader.AddLine(coord);
|
shader.AddLine(coord);
|
||||||
const std::string texture = "texture(" + sampler + ", coords)";
|
const std::string texture = "texture(" + sampler + ", coords)";
|
||||||
|
|
||||||
// TEXS has two destination registers. RG goes into gpr0+0 and gpr0+1, and BA goes
|
// TEXS has two destination registers. RG goes into gpr0+0 and gpr0+1, and BA
|
||||||
// into gpr28+0 and gpr28+1
|
// goes into gpr28+0 and gpr28+1
|
||||||
size_t offset{};
|
size_t offset{};
|
||||||
|
|
||||||
for (const auto& dest : {instr.gpr0.Value(), instr.gpr28.Value()}) {
|
for (const auto& dest : {instr.gpr0.Value(), instr.gpr28.Value()}) {
|
||||||
@@ -1412,8 +1455,8 @@ private:
|
|||||||
|
|
||||||
shader.AddLine("return true;");
|
shader.AddLine("return true;");
|
||||||
if (instr.pred.pred_index == static_cast<u64>(Pred::UnusedIndex)) {
|
if (instr.pred.pred_index == static_cast<u64>(Pred::UnusedIndex)) {
|
||||||
// If this is an unconditional exit then just end processing here, otherwise we
|
// If this is an unconditional exit then just end processing here, otherwise
|
||||||
// have to account for the possibility of the condition not being met, so
|
// we have to account for the possibility of the condition not being met, so
|
||||||
// continue processing the next instruction.
|
// continue processing the next instruction.
|
||||||
offset = PROGRAM_END - 1;
|
offset = PROGRAM_END - 1;
|
||||||
}
|
}
|
||||||
@@ -1435,6 +1478,11 @@ private:
|
|||||||
regs.SetRegisterToInputAttibute(instr.gpr0, attribute.element, attribute.index);
|
regs.SetRegisterToInputAttibute(instr.gpr0, attribute.element, attribute.index);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case OpCode::Id::SSY: {
|
||||||
|
// The SSY opcode tells the GPU where to re-converge divergent execution paths, we
|
||||||
|
// can ignore this when generating GLSL code.
|
||||||
|
break;
|
||||||
|
}
|
||||||
default: {
|
default: {
|
||||||
NGLOG_CRITICAL(HW_GPU, "Unhandled instruction: {}", opcode->GetName());
|
NGLOG_CRITICAL(HW_GPU, "Unhandled instruction: {}", opcode->GetName());
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
|
|||||||
Reference in New Issue
Block a user