mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-11-15 02:29:51 +01:00
Merge branch 'master' into TemporaryHackishBranch
# Conflicts: # Core/Util/AudioFormat.cpp # bad path was disabled so let's just sync # UI/CwCheatScreen.cpp # just because I keep parse function to use multiply cheat.db files
This commit is contained in:
commit
aa7b2430a0
47 files changed
+258
-177
No files matched your search
@@ -733,9 +733,11 @@ void ARM64XEmitter::EncodeLoadStoreIndexedInst(u32 op, ARM64Reg Rt, ARM64Reg Rn,
|
||||
else if (size == 16)
|
||||
shift = 1;
|
||||
|
||||
_assert_msg_(DYNA_REC, ((imm >> shift) << shift) == imm, "%s(INDEX_UNSIGNED): offset must be aligned %d", __FUNCTION__, imm);
|
||||
if (shift) {
|
||||
_assert_msg_(DYNA_REC, ((imm >> shift) << shift) == imm, "%s(INDEX_UNSIGNED): offset must be aligned %d", __FUNCTION__, imm);
|
||||
imm >>= shift;
|
||||
}
|
||||
|
||||
imm >>= shift;
|
||||
_assert_msg_(DYNA_REC, imm >= 0, "%s(INDEX_UNSIGNED): offset must be positive %d", __FUNCTION__, imm);
|
||||
_assert_msg_(DYNA_REC, !(imm & ~0xFFF), "%s(INDEX_UNSIGNED): offset too large %d", __FUNCTION__, imm);
|
||||
|
||||
|
||||
@@ -134,6 +134,27 @@ size_t VulkanPushBuffer::GetTotalSize() const {
|
||||
return sum;
|
||||
}
|
||||
|
||||
void VulkanPushBuffer::Map() {
|
||||
assert(!writePtr_);
|
||||
VkResult res = vkMapMemory(device_, buffers_[buf_].deviceMemory, 0, size_, 0, (void **)(&writePtr_));
|
||||
assert(writePtr_);
|
||||
assert(VK_SUCCESS == res);
|
||||
}
|
||||
|
||||
void VulkanPushBuffer::Unmap() {
|
||||
assert(writePtr_);
|
||||
/*
|
||||
// Should not need this since we use coherent memory.
|
||||
VkMappedMemoryRange range = { VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE };
|
||||
range.offset = 0;
|
||||
range.size = offset_;
|
||||
range.memory = buffers_[buf_].deviceMemory;
|
||||
vkFlushMappedMemoryRanges(device_, 1, &range);
|
||||
*/
|
||||
vkUnmapMemory(device_, buffers_[buf_].deviceMemory);
|
||||
writePtr_ = nullptr;
|
||||
}
|
||||
|
||||
VulkanDeviceAllocator::VulkanDeviceAllocator(VulkanContext *vulkan, size_t minSlabSize, size_t maxSlabSize)
|
||||
: vulkan_(vulkan), lastSlab_(0), minSlabSize_(minSlabSize), maxSlabSize_(maxSlabSize), memoryTypeIndex_(UNDEFINED_MEMORY_TYPE), destroyed_(false) {
|
||||
assert((minSlabSize_ & (SLAB_GRAIN_SIZE - 1)) == 0);
|
||||
|
||||
@@ -46,26 +46,9 @@ public:
|
||||
Unmap();
|
||||
}
|
||||
|
||||
void Map() {
|
||||
assert(!writePtr_);
|
||||
VkResult res = vkMapMemory(device_, buffers_[buf_].deviceMemory, 0, size_, 0, (void **)(&writePtr_));
|
||||
assert(writePtr_);
|
||||
assert(VK_SUCCESS == res);
|
||||
}
|
||||
void Map();
|
||||
|
||||
void Unmap() {
|
||||
assert(writePtr_);
|
||||
/*
|
||||
// Should not need this since we use coherent memory.
|
||||
VkMappedMemoryRange range = { VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE };
|
||||
range.offset = 0;
|
||||
range.size = offset_;
|
||||
range.memory = buffers_[buf_].deviceMemory;
|
||||
vkFlushMappedMemoryRanges(device_, 1, &range);
|
||||
*/
|
||||
vkUnmapMemory(device_, buffers_[buf_].deviceMemory);
|
||||
writePtr_ = nullptr;
|
||||
}
|
||||
void Unmap();
|
||||
|
||||
// When using the returned memory, make sure to bind the returned vkbuf.
|
||||
// This will later allow for handling overflow correctly.
|
||||
|
||||
+21
-2
@@ -87,7 +87,12 @@ bool CheatFileParser::Parse() {
|
||||
getline(file_, line, '\n');
|
||||
line = TrimString(line);
|
||||
|
||||
if (line.length() > 2 && line[0] == '_') {
|
||||
// Minimum length is set to 5 just to match GetCodesList() function
|
||||
// which discards anything shorter when called anyway.
|
||||
// It's decided from shortest possible _ lines name of the game "_G N+"
|
||||
// and a minimum of 1 displayable character in cheat name string "_C0 1"
|
||||
// which both equal to 5 characters.
|
||||
if (line.length() >= 5 && line[0] == '_') {
|
||||
ParseLine(line);
|
||||
} else if (line.length() >= 2 && line[0] == '/' && line[1] == '/') {
|
||||
// Comment, ignore.
|
||||
@@ -340,7 +345,21 @@ std::vector<std::string> CWCheatEngine::GetCodesList() {
|
||||
std::string line;
|
||||
getline(list, line, '\n');
|
||||
|
||||
if (line.length() > 3 && (line.substr(0, 1) == "_" || line.substr(0, 2) == "//")) {
|
||||
bool validCheatLine = false;
|
||||
// This function is called by cheat menu(UI) which doesn't support empty names
|
||||
// minimum 1 non space character is required starting from 5 position.
|
||||
// It also goes through other "_" lines, but they all have to meet this requirement anyway
|
||||
// so we don't have to specify any syntax checks here that are made by cheat engine.
|
||||
if (line.length() >= 5 && line[0] == '_') {
|
||||
for (int i = 4; i < line.length(); i++) {
|
||||
if (line[i] != ' ') {
|
||||
validCheatLine = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Any lines not passing this check are discarded when we save changes to the cheat ini file
|
||||
if (validCheatLine || (line.length() >= 2 && line[0] == '/' && line[1] == '/') || (line.length() >= 1 && line[0] == '#')) {
|
||||
codesList.push_back(TrimString(line));
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -635,7 +635,7 @@ size_t hleFormatLogArgs(char *message, size_t sz, const char *argmask) {
|
||||
// TODO: Double? Does it ever happen?
|
||||
|
||||
default:
|
||||
_assert_msg_(HLE, false, "Invalid argmask character: %c", argmask[i]);
|
||||
_dbg_assert_msg_(HLE, false, "Invalid argmask character: %c", argmask[i]);
|
||||
APPEND_FMT(" -- invalid arg format: %c -- %08x", argmask[i], regval);
|
||||
break;
|
||||
}
|
||||
@@ -673,7 +673,7 @@ void hleDoLogInternal(LogTypes::LOG_TYPE t, LogTypes::LOG_LEVELS level, u64 res,
|
||||
// TODO: For now, floats are just shown as bits.
|
||||
fmt = "%s%08x=%s(%s)%s";
|
||||
} else {
|
||||
_assert_msg_(HLE, false, "Invalid return format: %c", retmask);
|
||||
_dbg_assert_msg_(HLE, false, "Invalid return format: %c", retmask);
|
||||
fmt = "%s%08llx=%s(%s)%s";
|
||||
}
|
||||
|
||||
|
||||
@@ -106,21 +106,6 @@ void ArmJit::DoState(PointerWrap &p)
|
||||
}
|
||||
}
|
||||
|
||||
// This is here so the savestate matches between jit and non-jit.
|
||||
void ArmJit::DoDummyState(PointerWrap &p)
|
||||
{
|
||||
auto s = p.Section("Jit", 1, 2);
|
||||
if (!s)
|
||||
return;
|
||||
|
||||
bool dummy = false;
|
||||
p.Do(dummy);
|
||||
if (s >= 2) {
|
||||
dummy = true;
|
||||
p.Do(dummy);
|
||||
}
|
||||
}
|
||||
|
||||
void ArmJit::FlushAll()
|
||||
{
|
||||
gpr.FlushAll();
|
||||
|
||||
@@ -39,7 +39,6 @@ public:
|
||||
virtual ~ArmJit();
|
||||
|
||||
void DoState(PointerWrap &p) override;
|
||||
void DoDummyState(PointerWrap &p) override;
|
||||
|
||||
const JitOptions &GetJitOptions() { return jo; }
|
||||
|
||||
|
||||
@@ -98,20 +98,6 @@ void Arm64Jit::DoState(PointerWrap &p) {
|
||||
}
|
||||
}
|
||||
|
||||
// This is here so the savestate matches between jit and non-jit.
|
||||
void Arm64Jit::DoDummyState(PointerWrap &p) {
|
||||
auto s = p.Section("Jit", 1, 2);
|
||||
if (!s)
|
||||
return;
|
||||
|
||||
bool dummy = false;
|
||||
p.Do(dummy);
|
||||
if (s >= 2) {
|
||||
dummy = true;
|
||||
p.Do(dummy);
|
||||
}
|
||||
}
|
||||
|
||||
void Arm64Jit::FlushAll()
|
||||
{
|
||||
gpr.FlushAll();
|
||||
|
||||
@@ -39,7 +39,6 @@ public:
|
||||
virtual ~Arm64Jit();
|
||||
|
||||
void DoState(PointerWrap &p) override;
|
||||
void DoDummyState(PointerWrap &p) override;
|
||||
|
||||
const JitOptions &GetJitOptions() { return jo; }
|
||||
|
||||
|
||||
@@ -50,20 +50,6 @@ void IRJit::DoState(PointerWrap &p) {
|
||||
frontend_.DoState(p);
|
||||
}
|
||||
|
||||
// This is here so the savestate matches between jit and non-jit.
|
||||
void IRJit::DoDummyState(PointerWrap &p) {
|
||||
auto s = p.Section("Jit", 1, 2);
|
||||
if (!s)
|
||||
return;
|
||||
|
||||
bool dummy = false;
|
||||
p.Do(dummy);
|
||||
if (s >= 2) {
|
||||
dummy = true;
|
||||
p.Do(dummy);
|
||||
}
|
||||
}
|
||||
|
||||
void IRJit::ClearCache() {
|
||||
ILOG("IRJit: Clearing the cache!");
|
||||
blocks_.Clear();
|
||||
|
||||
@@ -127,7 +127,6 @@ public:
|
||||
virtual ~IRJit();
|
||||
|
||||
void DoState(PointerWrap &p) override;
|
||||
void DoDummyState(PointerWrap &p) override;
|
||||
|
||||
const JitOptions &GetJitOptions() { return jo; }
|
||||
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
#include "ext/udis86/udis86.h"
|
||||
|
||||
#include "Common/StringUtils.h"
|
||||
#include "Common/ChunkFile.h"
|
||||
|
||||
#include "Core/Util/DisArm64.h"
|
||||
#include "Core/Config.h"
|
||||
|
||||
@@ -46,6 +48,20 @@ namespace MIPSComp {
|
||||
jit->Compile(currentMIPS->pc);
|
||||
}
|
||||
|
||||
void DoDummyJitState(PointerWrap &p) {
|
||||
// This is here so the savestate matches between jit and non-jit.
|
||||
auto s = p.Section("Jit", 1, 2);
|
||||
if (!s)
|
||||
return;
|
||||
|
||||
bool dummy = false;
|
||||
p.Do(dummy);
|
||||
if (s >= 2) {
|
||||
dummy = true;
|
||||
p.Do(dummy);
|
||||
}
|
||||
}
|
||||
|
||||
JitInterface *CreateNativeJit(MIPSState *mips) {
|
||||
#if PPSSPP_ARCH(ARM)
|
||||
return new MIPSComp::ArmJit(mips);
|
||||
|
||||
@@ -125,7 +125,6 @@ namespace MIPSComp {
|
||||
virtual JitBlockCache *GetBlockCache() = 0;
|
||||
virtual void InvalidateCacheAt(u32 em_address, int length = 4) = 0;
|
||||
virtual void DoState(PointerWrap &p) = 0;
|
||||
virtual void DoDummyState(PointerWrap &p) = 0;
|
||||
virtual void RunLoopUntil(u64 globalticks) = 0;
|
||||
virtual void Compile(u32 em_address) = 0;
|
||||
virtual void ClearCache() = 0;
|
||||
@@ -147,5 +146,7 @@ namespace MIPSComp {
|
||||
|
||||
extern JitInterface *jit;
|
||||
|
||||
void DoDummyJitState(PointerWrap &p);
|
||||
|
||||
JitInterface *CreateNativeJit(MIPSState *mips);
|
||||
}
|
||||
+1
-1
@@ -262,7 +262,7 @@ void MIPSState::DoState(PointerWrap &p) {
|
||||
if (MIPSComp::jit)
|
||||
MIPSComp::jit->DoState(p);
|
||||
else
|
||||
MIPSComp::jit->DoDummyState(p);
|
||||
MIPSComp::DoDummyJitState(p);
|
||||
|
||||
p.DoArray(r, sizeof(r) / sizeof(r[0]));
|
||||
p.DoArray(f, sizeof(f) / sizeof(f[0]));
|
||||
|
||||
@@ -66,21 +66,6 @@ void MipsJit::DoState(PointerWrap &p)
|
||||
}
|
||||
}
|
||||
|
||||
// This is here so the savestate matches between jit and non-jit.
|
||||
void MipsJit::DoDummyState(PointerWrap &p)
|
||||
{
|
||||
auto s = p.Section("Jit", 1, 2);
|
||||
if (!s)
|
||||
return;
|
||||
|
||||
bool dummy = false;
|
||||
p.Do(dummy);
|
||||
if (s >= 2) {
|
||||
dummy = true;
|
||||
p.Do(dummy);
|
||||
}
|
||||
}
|
||||
|
||||
void MipsJit::FlushAll()
|
||||
{
|
||||
//gpr.FlushAll();
|
||||
|
||||
@@ -38,7 +38,6 @@ public:
|
||||
MipsJit(MIPSState *mips);
|
||||
|
||||
void DoState(PointerWrap &p) override;
|
||||
void DoDummyState(PointerWrap &p) override;
|
||||
|
||||
// Compiled ops should ignore delay slots
|
||||
// the compiler will take care of them by itself
|
||||
|
||||
@@ -142,21 +142,6 @@ void Jit::DoState(PointerWrap &p) {
|
||||
CBreakPoints::SetSkipFirst(0);
|
||||
}
|
||||
|
||||
// This is here so the savestate matches between jit and non-jit.
|
||||
void Jit::DoDummyState(PointerWrap &p) {
|
||||
auto s = p.Section("Jit", 1, 2);
|
||||
if (!s)
|
||||
return;
|
||||
|
||||
bool dummy = false;
|
||||
p.Do(dummy);
|
||||
if (s >= 2) {
|
||||
dummy = true;
|
||||
p.Do(dummy);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Jit::GetStateAndFlushAll(RegCacheState &state) {
|
||||
gpr.GetState(state.gpr);
|
||||
fpr.GetState(state.fpr);
|
||||
|
||||
@@ -52,7 +52,6 @@ public:
|
||||
const JitOptions &GetJitOptions() { return jo; }
|
||||
|
||||
void DoState(PointerWrap &p) override;
|
||||
void DoDummyState(PointerWrap &p) override;
|
||||
|
||||
// Compiled ops should ignore delay slots
|
||||
// the compiler will take care of them by itself
|
||||
|
||||
+32
-11
@@ -26,7 +26,7 @@
|
||||
|
||||
void AdjustVolumeBlockStandard(s16 *out, s16 *in, size_t size, int leftVol, int rightVol) {
|
||||
#ifdef _M_SSE
|
||||
if (leftVol <= 0x7fff && rightVol <= 0x7fff) {
|
||||
if (leftVol <= 0x7fff && -leftVol <= 0x8000 && rightVol <= 0x7fff && -rightVol <= 0x8000) {
|
||||
__m128i volume = _mm_set_epi16(leftVol, rightVol, leftVol, rightVol, leftVol, rightVol, leftVol, rightVol);
|
||||
while (size >= 16) {
|
||||
__m128i indata1 = _mm_loadu_si128((__m128i *)in);
|
||||
@@ -37,25 +37,46 @@ void AdjustVolumeBlockStandard(s16 *out, s16 *in, size_t size, int leftVol, int
|
||||
out += 16;
|
||||
size -= 16;
|
||||
}
|
||||
} else {
|
||||
// We have to shift inside the loop to avoid the signed multiply issue.
|
||||
leftVol >>= 1;
|
||||
rightVol >>= 1;
|
||||
__m128i volume = _mm_set_epi16(leftVol, rightVol, leftVol, rightVol, leftVol, rightVol, leftVol, rightVol);
|
||||
}
|
||||
#if 0
|
||||
// This path wraps instead of clamps in _mm_slli_epi16. Needs fixing.
|
||||
else {
|
||||
// We have to shift inside the loop to avoid the signed 16-bit multiply issue.
|
||||
int leftShift = 0;
|
||||
int leftVol16 = leftVol;
|
||||
while (leftVol16 > 0x7fff || -leftVol16 > 0x8000) {
|
||||
++leftShift;
|
||||
leftVol16 >>= 1;
|
||||
}
|
||||
int rightShift = 0;
|
||||
int rightVol16 = rightVol;
|
||||
while (rightVol16 > 0x7fff || -rightVol16 > 0x8000) {
|
||||
++rightShift;
|
||||
rightVol16 >>= 1;
|
||||
}
|
||||
__m128i volume = _mm_set_epi16(leftVol16, rightVol16, leftVol16, rightVol16, leftVol16, rightVol16, leftVol16, rightVol16);
|
||||
while (size >= 16) {
|
||||
__m128i indata1 = _mm_loadu_si128((__m128i *)in);
|
||||
__m128i indata2 = _mm_loadu_si128((__m128i *)(in + 8));
|
||||
_mm_storeu_si128((__m128i *)out, _mm_slli_epi16(_mm_mulhi_epi16(indata1, volume), 1));
|
||||
_mm_storeu_si128((__m128i *)(out + 8), _mm_slli_epi16(_mm_mulhi_epi16(indata2, volume), 1));
|
||||
_mm_storeu_si128((__m128i *)out, _mm_slli_epi16(_mm_mulhi_epi16(indata1, volume), leftShift));
|
||||
_mm_storeu_si128((__m128i *)(out + 8), _mm_slli_epi16(_mm_mulhi_epi16(indata2, volume), rightShift));
|
||||
in += 16;
|
||||
out += 16;
|
||||
size -= 16;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
for (size_t i = 0; i < size; i += 2) {
|
||||
out[i] = ApplySampleVolume(in[i], leftVol);
|
||||
out[i + 1] = ApplySampleVolume(in[i + 1], rightVol);
|
||||
#endif
|
||||
if (leftVol <= 0x7fff && -leftVol <= 0x8000 && rightVol <= 0x7fff && -rightVol <= 0x8000) {
|
||||
for (size_t i = 0; i < size; i += 2) {
|
||||
out[i] = ApplySampleVolume(in[i], leftVol);
|
||||
out[i + 1] = ApplySampleVolume(in[i + 1], rightVol);
|
||||
}
|
||||
} else {
|
||||
for (size_t i = 0; i < size; i += 2) {
|
||||
out[i] = ApplySampleVolume20Bit(in[i], leftVol);
|
||||
out[i + 1] = ApplySampleVolume20Bit(in[i + 1], rightVol);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -59,6 +59,12 @@ static inline s16 ApplySampleVolume(s16 sample, int vol) {
|
||||
#endif
|
||||
}
|
||||
|
||||
// We sacrifice a little volume precision to fit in 32 bits, for speed.
|
||||
// Probably not worth it to make a special path for 64-bit CPUs.
|
||||
static inline s16 ApplySampleVolume20Bit(s16 sample, int vol20) {
|
||||
return clamp_s16((sample * (vol20 >> 4)) >> 12);
|
||||
}
|
||||
|
||||
void SetupAudioFormats();
|
||||
void AdjustVolumeBlockStandard(s16 *out, s16 *in, size_t size, int leftVol, int rightVol);
|
||||
void ConvertS16ToF32(float *ou, const s16 *in, size_t size);
|
||||
|
||||
@@ -55,9 +55,16 @@ void AdjustVolumeBlockNEON(s16 *out, s16 *in, size_t size, int leftVol, int righ
|
||||
size -= 16;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < size; i += 2) {
|
||||
out[i] = ApplySampleVolume(in[i], leftVol);
|
||||
out[i + 1] = ApplySampleVolume(in[i + 1], rightVol);
|
||||
if (leftVol <= 0x7fff && -leftVol <= 0x8000 && rightVol <= 0x7fff && -rightVol <= 0x8000) {
|
||||
for (size_t i = 0; i < size; i += 2) {
|
||||
out[i] = ApplySampleVolume(in[i], leftVol);
|
||||
out[i + 1] = ApplySampleVolume(in[i + 1], rightVol);
|
||||
}
|
||||
} else {
|
||||
for (size_t i = 0; i < size; i += 2) {
|
||||
out[i] = ApplySampleVolume20Bit(in[i], leftVol);
|
||||
out[i + 1] = ApplySampleVolume20Bit(in[i + 1], rightVol);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -136,6 +136,8 @@ FramebufferManagerCommon::~FramebufferManagerCommon() {
|
||||
DestroyFramebuf(vfb);
|
||||
}
|
||||
bvfbs_.clear();
|
||||
|
||||
SetNumExtraFBOs(0);
|
||||
}
|
||||
|
||||
void FramebufferManagerCommon::Init() {
|
||||
@@ -201,7 +203,7 @@ bool FramebufferManagerCommon::ShouldDownloadFramebuffer(const VirtualFramebuffe
|
||||
|
||||
void FramebufferManagerCommon::SetNumExtraFBOs(int num) {
|
||||
for (size_t i = 0; i < extraFBOs_.size(); i++) {
|
||||
extraFBOs_[i]->Release();
|
||||
extraFBOs_[i]->ReleaseAssertLast();
|
||||
}
|
||||
extraFBOs_.clear();
|
||||
for (int i = 0; i < num; i++) {
|
||||
@@ -210,7 +212,8 @@ void FramebufferManagerCommon::SetNumExtraFBOs(int num) {
|
||||
extraFBOs_.push_back(fbo);
|
||||
}
|
||||
currentRenderVfb_ = 0;
|
||||
draw_->BindFramebufferAsRenderTarget(nullptr, { Draw::RPAction::KEEP, Draw::RPAction::KEEP });
|
||||
if (num != 0)
|
||||
draw_->BindFramebufferAsRenderTarget(nullptr, { Draw::RPAction::KEEP, Draw::RPAction::KEEP });
|
||||
}
|
||||
|
||||
// Heuristics to figure out the size of FBO to create.
|
||||
|
||||
@@ -698,7 +698,12 @@ void VertexDecoderJitCache::Jit_PosS16Through() {
|
||||
}
|
||||
|
||||
void VertexDecoderJitCache::Jit_NormalS8() {
|
||||
LDRH(INDEX_UNSIGNED, tempReg1, srcReg, dec_->nrmoff);
|
||||
// nrmoff can be odd in case of byte-only vertices! odd unsigned offsets are not allowed for LDRH.
|
||||
// Switching to LDRB.
|
||||
// Only seen this in a crash log.
|
||||
LDRB(INDEX_UNSIGNED, tempReg1, srcReg, dec_->nrmoff);
|
||||
LDRB(INDEX_UNSIGNED, tempReg3, srcReg, dec_->nrmoff + 1);
|
||||
ORR(tempReg1, tempReg1, tempReg3, ArithOption(tempReg3, ST_LSL, 8));
|
||||
LDRB(INDEX_UNSIGNED, tempReg3, srcReg, dec_->nrmoff + 2);
|
||||
ORR(tempReg1, tempReg1, tempReg3, ArithOption(tempReg3, ST_LSL, 16));
|
||||
STR(INDEX_UNSIGNED, tempReg1, dstReg, dec_->decFmt.nrmoff);
|
||||
|
||||
@@ -148,9 +148,13 @@ void ShaderManagerDX9::PSSetColorUniform3(int creg, u32 color) {
|
||||
}
|
||||
|
||||
void ShaderManagerDX9::PSSetColorUniform3Alpha255(int creg, u32 color, u8 alpha) {
|
||||
float f[4];
|
||||
Uint8x3ToFloat4_AlphaUint8(f, color, alpha);
|
||||
device_->SetPixelShaderConstantF(creg, f, 1);
|
||||
const float col[4] = {
|
||||
(float)((color & 0xFF)),
|
||||
(float)((color & 0xFF00) >> 8),
|
||||
(float)((color & 0xFF0000) >> 16),
|
||||
(float)alpha,
|
||||
};
|
||||
device_->SetPixelShaderConstantF(creg, col, 1);
|
||||
}
|
||||
|
||||
void ShaderManagerDX9::PSSetFloat(int creg, float value) {
|
||||
|
||||
@@ -250,7 +250,6 @@ FramebufferManagerGLES::~FramebufferManagerGLES() {
|
||||
if (stencilUploadProgram_) {
|
||||
glsl_destroy(stencilUploadProgram_);
|
||||
}
|
||||
SetNumExtraFBOs(0);
|
||||
|
||||
for (auto it = tempFBOs_.begin(), end = tempFBOs_.end(); it != end; ++it) {
|
||||
it->second.fbo->Release();
|
||||
|
||||
@@ -69,7 +69,8 @@ DepalShaderCacheVulkan::~DepalShaderCacheVulkan() {
|
||||
|
||||
void DepalShaderCacheVulkan::DeviceLost() {
|
||||
Clear();
|
||||
vulkan_->Delete().QueueDeleteShaderModule(vshader_);
|
||||
if (vshader_)
|
||||
vulkan_->Delete().QueueDeleteShaderModule(vshader_);
|
||||
draw_ = nullptr;
|
||||
vulkan_ = nullptr;
|
||||
}
|
||||
|
||||
@@ -247,9 +247,11 @@ void DrawEngineVulkan::DestroyDeviceObjects() {
|
||||
delete nullTexture_;
|
||||
nullTexture_ = nullptr;
|
||||
}
|
||||
vertexCache_->Destroy(vulkan_);
|
||||
delete vertexCache_;
|
||||
vertexCache_ = nullptr;
|
||||
if (vertexCache_) {
|
||||
vertexCache_->Destroy(vulkan_);
|
||||
delete vertexCache_;
|
||||
vertexCache_ = nullptr;
|
||||
}
|
||||
// Need to clear this to get rid of all remaining references to the dead buffers.
|
||||
vai_.Iterate([](uint32_t hash, VertexArrayInfoVulkan *vai) {
|
||||
delete vai;
|
||||
|
||||
@@ -301,8 +301,7 @@ static VulkanPipeline *CreateVulkanPipeline(VkDevice device, VkPipelineCache pip
|
||||
|
||||
VulkanPipeline *PipelineManagerVulkan::GetOrCreatePipeline(VkPipelineLayout layout, VkRenderPass renderPass, const VulkanPipelineRasterStateKey &rasterKey, const DecVtxFormat *decFmt, VulkanVertexShader *vs, VulkanFragmentShader *fs, bool useHwTransform) {
|
||||
VulkanPipelineKey key{};
|
||||
if (!renderPass)
|
||||
Crash();
|
||||
_assert_msg_(G3D, renderPass, "Can't create a pipeline with a null renderpass");
|
||||
|
||||
key.raster = rasterKey;
|
||||
key.renderPass = renderPass;
|
||||
|
||||
@@ -27,6 +27,23 @@ For the latest source code, see [our github page](https://github.com/hrydgard/pp
|
||||
|
||||
For build instructions and other development tutorials, see the [wiki](https://github.com/hrydgard/ppsspp/wiki).
|
||||
|
||||
|
||||
What's new in 1.5.0
|
||||
-------------------
|
||||
* Full Vulkan support, also for Android now. Very fast on supported devices. (#10033, #10049)
|
||||
* Smarter graphics state management, reduced CPU consumption on all backends (#9899)
|
||||
* Android: Support for Arabic and other scripts we couldn't support before
|
||||
* Fix Android widgets, screen scaling (#10145)
|
||||
* Fixes to video dumping
|
||||
* Geometry problems fixed in Medal of Honor
|
||||
* Implement immediate draws, fixing Thrillville (#7459)
|
||||
* Software rendering improvements, speed and accuracy
|
||||
* Hardware tesselation of PSP Beziers and Splines (used by a few games)
|
||||
* Partial sceUsbGps and sceUsbCam support (Android)
|
||||
* Android "Sustained performance mode" to avoid thermal throttling (#9901)
|
||||
* Linux controller mapping fixes (#9997)
|
||||
* Assorted bugfixes and compatibility improvements
|
||||
|
||||
What's new in 1.4.2
|
||||
-------------------
|
||||
* Fixed longstanding bug causing games to crash on ARM64
|
||||
|
||||
+14
-12
@@ -65,9 +65,9 @@ void CwCheatScreen::CreateCodeList() {
|
||||
bEnableCheat.clear();
|
||||
formattedList_.clear();
|
||||
for (size_t i = 0; i < cheatList.size(); i++) {
|
||||
if (cheatList[i].substr(0, 2) == "_C") {
|
||||
if (cheatList[i][0] == '_' && cheatList[i][1] == 'C') {
|
||||
formattedList_.push_back(cheatList[i].substr(4));
|
||||
if (cheatList[i].substr(2, 1) == "0") {
|
||||
if (cheatList[i][2] == '0') {
|
||||
bEnableCheat.push_back(false);
|
||||
} else {
|
||||
bEnableCheat.push_back(true);
|
||||
@@ -136,11 +136,11 @@ UI::EventReturn CwCheatScreen::OnEnableAll(UI::EventParams ¶ms) {
|
||||
enableAll = !enableAll;
|
||||
File::OpenCPPFile(fs, activeCheatFile, std::ios::out);
|
||||
for (int j = 0; j < (int)cheatList.size(); j++) {
|
||||
if (cheatList[j].substr(0, 2) == "_C") {
|
||||
if (cheatList[j].substr(2, 1) == "0" && enableAll) {
|
||||
cheatList[j].replace(2, 1, "1");
|
||||
} else if (cheatList[j].substr(2, 1) != "0" && !enableAll) {
|
||||
cheatList[j].replace(2, 1, "0");
|
||||
if (cheatList[j][0] == '_' && cheatList[j][1] == 'C') {
|
||||
if (cheatList[j][2] == '0' && enableAll) {
|
||||
cheatList[j][2] = '1';
|
||||
} else if (cheatList[j][2] != '0' && !enableAll) {
|
||||
cheatList[j][2] = '0';
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -181,6 +181,8 @@ UI::EventReturn CwCheatScreen::OnEditCheatFile(UI::EventParams ¶ms) {
|
||||
|
||||
void CwCheatScreen::ParseCheatDB(std::string line, std::vector<std::string> title, std::vector<std::string> newList, std::string cheatFile) {
|
||||
bool finished = false, skip = false;
|
||||
std::string gameID = StringFromFormat("_S %s-%s", gameTitle.substr(0, 4).c_str(), gameTitle.substr(4).c_str());
|
||||
|
||||
std::fstream fs;
|
||||
File::OpenCPPFile(fs, cheatFile, std::ios::in);
|
||||
|
||||
@@ -190,7 +192,7 @@ void CwCheatScreen::ParseCheatDB(std::string line, std::vector<std::string> titl
|
||||
|
||||
while (fs.good()) {
|
||||
getline(fs, line); // get line from file
|
||||
if (line == "_S " + gameTitle.substr(0, 4) + "-" + gameTitle.substr(4)) {
|
||||
if (line == gameID) {
|
||||
title.push_back(line);
|
||||
getline(fs, line);
|
||||
title.push_back(line);
|
||||
@@ -198,7 +200,7 @@ void CwCheatScreen::ParseCheatDB(std::string line, std::vector<std::string> titl
|
||||
if (finished == false) {
|
||||
getline(fs, line);
|
||||
}
|
||||
if (line.substr(0, 2) == "_C") {
|
||||
if (line[0] == '_' && line[1] == 'C') {
|
||||
//Test if cheat already exists in cheatList
|
||||
for (size_t j = 0; j < formattedList_.size(); j++) {
|
||||
if (line.substr(4) == formattedList_[j]) {
|
||||
@@ -212,14 +214,14 @@ void CwCheatScreen::ParseCheatDB(std::string line, std::vector<std::string> titl
|
||||
do {
|
||||
newList.push_back(line);
|
||||
getline(fs, line);
|
||||
} while (line.substr(0, 2) == "_L");
|
||||
} while (line[0] == '_' && line[1] == 'L');
|
||||
finished = true;
|
||||
}
|
||||
else {
|
||||
continue;
|
||||
}
|
||||
loop:;
|
||||
} while (line.substr(0, 2) != "_S");
|
||||
} while (fs.good() && line[0] != '_' && line[1] != 'S');
|
||||
finished = true;
|
||||
}
|
||||
if (finished == true)
|
||||
@@ -234,7 +236,7 @@ void CwCheatScreen::ParseCheatDB(std::string line, std::vector<std::string> titl
|
||||
File::OpenCPPFile(fs, activeCheatFile, std::ios::out | std::ios::app);
|
||||
|
||||
auto it = title.begin();
|
||||
if (title2.substr(0, 2) != "_S" && it != title.end() && (++it) != title.end()) {
|
||||
if (title2[0] != '_' && title2[1] != 'S' && it != title.end() && (++it) != title.end()) {
|
||||
fs << title[0] << "\n" << title[1];
|
||||
}
|
||||
|
||||
|
||||
@@ -534,6 +534,7 @@ void CreditsScreen::CreateViews() {
|
||||
}
|
||||
root_->Add(new Button(cr->T("PPSSPP Forums"), new AnchorLayoutParams(260, 64, 10, NONE, NONE, 84, false)))->OnClick.Handle(this, &CreditsScreen::OnForums);
|
||||
root_->Add(new Button("www.ppsspp.org", new AnchorLayoutParams(260, 64, 10, NONE, NONE, 158, false)))->OnClick.Handle(this, &CreditsScreen::OnPPSSPPOrg);
|
||||
root_->Add(new Button(cr->T("Privacy Policy"), new AnchorLayoutParams(260, 64, 10, NONE, NONE, 232, false)))->OnClick.Handle(this, &CreditsScreen::OnPrivacy);
|
||||
#ifdef __ANDROID__
|
||||
root_->Add(new Button(cr->T("Share PPSSPP"), new AnchorLayoutParams(260, 64, NONE, NONE, 10, 84, false)))->OnClick.Handle(this, &CreditsScreen::OnShare);
|
||||
root_->Add(new Button(cr->T("Twitter @PPSSPP_emu"), new AnchorLayoutParams(260, 64, NONE, NONE, 10, 154, false)))->OnClick.Handle(this, &CreditsScreen::OnTwitter);
|
||||
@@ -568,6 +569,11 @@ UI::EventReturn CreditsScreen::OnPPSSPPOrg(UI::EventParams &e) {
|
||||
return UI::EVENT_DONE;
|
||||
}
|
||||
|
||||
UI::EventReturn CreditsScreen::OnPrivacy(UI::EventParams &e) {
|
||||
LaunchBrowser("https://www.ppsspp.org/privacy.html");
|
||||
return UI::EVENT_DONE;
|
||||
}
|
||||
|
||||
UI::EventReturn CreditsScreen::OnForums(UI::EventParams &e) {
|
||||
LaunchBrowser("https://forums.ppsspp.org");
|
||||
return UI::EVENT_DONE;
|
||||
|
||||
+1
-1
@@ -142,8 +142,8 @@ private:
|
||||
|
||||
UI::EventReturn OnSupport(UI::EventParams &e);
|
||||
UI::EventReturn OnPPSSPPOrg(UI::EventParams &e);
|
||||
UI::EventReturn OnPrivacy(UI::EventParams &e);
|
||||
UI::EventReturn OnForums(UI::EventParams &e);
|
||||
UI::EventReturn OnChineseForum(UI::EventParams &e);
|
||||
UI::EventReturn OnShare(UI::EventParams &e);
|
||||
UI::EventReturn OnTwitter(UI::EventParams &e);
|
||||
|
||||
|
||||
+4
-1
@@ -613,12 +613,14 @@ static void UIThemeInit() {
|
||||
|
||||
void RenderOverlays(UIContext *dc, void *userdata);
|
||||
|
||||
void NativeInitGraphics(GraphicsContext *graphicsContext) {
|
||||
bool NativeInitGraphics(GraphicsContext *graphicsContext) {
|
||||
ILOG("NativeInitGraphics");
|
||||
_assert_msg_(G3D, graphicsContext, "No graphics context!");
|
||||
|
||||
using namespace Draw;
|
||||
Core_SetGraphicsContext(graphicsContext);
|
||||
g_draw = graphicsContext->GetDrawContext();
|
||||
_assert_msg_(G3D, g_draw, "No draw context available!");
|
||||
|
||||
ui_draw2d.SetAtlas(&ui_atlas);
|
||||
ui_draw2d_front.SetAtlas(&ui_atlas);
|
||||
@@ -694,6 +696,7 @@ void NativeInitGraphics(GraphicsContext *graphicsContext) {
|
||||
|
||||
g_graphicsInited = true;
|
||||
ILOG("NativeInitGraphics completed");
|
||||
return true;
|
||||
}
|
||||
|
||||
void NativeShutdownGraphics() {
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="org.ppsspp.ppsspp"
|
||||
android:installLocation="auto"
|
||||
android:versionCode="14200000"
|
||||
android:versionName="1.4.2.0">
|
||||
android:versionCode="15000000"
|
||||
android:versionName="1.5.0.0">
|
||||
<!-- For the next release: Note that versionCode should be in the format xyzzrrrr -->
|
||||
|
||||
<uses-sdk
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
plugins {
|
||||
id 'com.gladed.androidgitversion' version '0.3.4'
|
||||
id 'com.gladed.androidgitversion' version '0.4.3'
|
||||
}
|
||||
apply plugin: 'com.android.application'
|
||||
|
||||
@@ -7,6 +7,7 @@ androidGitVersion {
|
||||
codeFormat = "MNPPBBBB"
|
||||
format = "%tag%%-count%%-branch%%-dirty%"
|
||||
prefix = "v" // Only tags beginning with v are considered.
|
||||
untrackedIsDirty = false
|
||||
}
|
||||
|
||||
android {
|
||||
|
||||
@@ -742,6 +742,8 @@ extern "C" void Java_org_ppsspp_ppsspp_NativeRenderer_displayInit(JNIEnv * env,
|
||||
|
||||
if (javaGL && !graphicsContext) {
|
||||
graphicsContext = new AndroidJavaEGLGraphicsContext();
|
||||
} else if (!graphicsContext) {
|
||||
_assert_msg_(G3D, false, "No graphics context in displayInit?");
|
||||
}
|
||||
|
||||
if (renderer_inited) {
|
||||
@@ -750,7 +752,6 @@ extern "C" void Java_org_ppsspp_ppsspp_NativeRenderer_displayInit(JNIEnv * env,
|
||||
NativeShutdownGraphics();
|
||||
NativeDeviceRestore();
|
||||
NativeInitGraphics(graphicsContext);
|
||||
|
||||
ILOG("Restored.");
|
||||
} else {
|
||||
ILOG("NativeApp.displayInit() first time");
|
||||
@@ -1139,6 +1140,7 @@ retry:
|
||||
}
|
||||
|
||||
delete graphicsContext;
|
||||
graphicsContext = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,17 +20,18 @@ class LocationHelper implements LocationListener {
|
||||
void startLocationUpdates() {
|
||||
Log.d(TAG, "startLocationUpdates");
|
||||
if (!mLocationEnable) {
|
||||
boolean isGPSEnabled = mLocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
|
||||
boolean isNetworkEnabled = mLocationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
|
||||
|
||||
boolean isGPSEnabled = false;
|
||||
boolean isNetworkEnabled = false;
|
||||
try {
|
||||
isGPSEnabled = mLocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
|
||||
isNetworkEnabled = mLocationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
|
||||
mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 0, this);
|
||||
mLocationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 1000, 0, this);
|
||||
mLocationEnable = true;
|
||||
} catch (SecurityException e) {
|
||||
Log.e(TAG, "Cannot start location updates: " + e.toString());
|
||||
}
|
||||
if(!isGPSEnabled && !isNetworkEnabled) {
|
||||
if (!isGPSEnabled && !isNetworkEnabled) {
|
||||
Log.i(TAG, "No location provider found");
|
||||
// TODO: notify user
|
||||
}
|
||||
|
||||
+1
-1
Submodule assets/lang updated: 4fddbc9d30...c37028e6b6.
@@ -49,7 +49,7 @@ void NativeInit(int argc, const char *argv[], const char *savegame_dir, const ch
|
||||
|
||||
// Runs after NativeInit() at some point. May (and probably should) call OpenGL.
|
||||
// Should not initialize anything screen-size-dependent - do that in NativeResized.
|
||||
void NativeInitGraphics(GraphicsContext *graphicsContext);
|
||||
bool NativeInitGraphics(GraphicsContext *graphicsContext);
|
||||
|
||||
// Signals that you need to forget all buffered OpenGL resources,
|
||||
// like textures, vbo etc.
|
||||
|
||||
@@ -467,7 +467,8 @@ void VulkanQueueRunner::PerformRenderPass(const VKRStep &step, VkCommandBuffer c
|
||||
vkCmdEndRenderPass(cmd);
|
||||
|
||||
// Transition the framebuffer if requested.
|
||||
if (fb && step.render.finalColorLayout != VK_IMAGE_LAYOUT_UNDEFINED) {
|
||||
// Don't need to transition it if VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL.
|
||||
if (fb && step.render.finalColorLayout != VK_IMAGE_LAYOUT_UNDEFINED && step.render.finalColorLayout != VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) {
|
||||
VkImageMemoryBarrier barrier{};
|
||||
barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
|
||||
barrier.oldLayout = fb->color.layout;
|
||||
@@ -490,6 +491,9 @@ void VulkanQueueRunner::PerformRenderPass(const VKRStep &step, VkCommandBuffer c
|
||||
case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
|
||||
barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
|
||||
break;
|
||||
case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
|
||||
barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT;
|
||||
break;
|
||||
default:
|
||||
Crash();
|
||||
}
|
||||
@@ -517,8 +521,8 @@ void VulkanQueueRunner::PerformBindFramebufferAsRenderTarget(const VKRStep &step
|
||||
// Now, if the image needs transitioning, let's transition.
|
||||
// The backbuffer does not, that's handled by VulkanContext.
|
||||
if (step.render.framebuffer->color.layout != VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) {
|
||||
VkAccessFlags srcAccessMask;
|
||||
VkPipelineStageFlags srcStage;
|
||||
VkAccessFlags srcAccessMask = 0;
|
||||
VkPipelineStageFlags srcStage = 0;
|
||||
switch (fb->color.layout) {
|
||||
case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
|
||||
srcAccessMask = VK_ACCESS_SHADER_READ_BIT;
|
||||
@@ -533,7 +537,7 @@ void VulkanQueueRunner::PerformBindFramebufferAsRenderTarget(const VKRStep &step
|
||||
srcStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
|
||||
break;
|
||||
default:
|
||||
Crash();
|
||||
_dbg_assert_msg_(G3D, false, "PerformBindRT: Unexpected color layout %d", (int)fb->color.layout);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -545,8 +549,8 @@ void VulkanQueueRunner::PerformBindFramebufferAsRenderTarget(const VKRStep &step
|
||||
fb->color.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
}
|
||||
if (fb->depth.layout != VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) {
|
||||
VkAccessFlags srcAccessMask;
|
||||
VkPipelineStageFlags srcStage;
|
||||
VkAccessFlags srcAccessMask = 0;
|
||||
VkPipelineStageFlags srcStage = 0;
|
||||
|
||||
switch (fb->depth.layout) {
|
||||
case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
|
||||
@@ -562,7 +566,7 @@ void VulkanQueueRunner::PerformBindFramebufferAsRenderTarget(const VKRStep &step
|
||||
srcStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
|
||||
break;
|
||||
default:
|
||||
Crash();
|
||||
_dbg_assert_msg_(G3D, false, "PerformBindRT: Unexpected depth layout %d", (int)fb->color.layout);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -791,7 +795,8 @@ void VulkanQueueRunner::SetupTransitionToTransferSrc(VKRImage &img, VkImageMemor
|
||||
stage |= VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
|
||||
break;
|
||||
default:
|
||||
Crash();
|
||||
_dbg_assert_msg_(G3D, false, "Transition from this layout to transfer src not supported (%d)", (int)img.layout);
|
||||
break;
|
||||
}
|
||||
barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
|
||||
barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
|
||||
@@ -826,7 +831,8 @@ void VulkanQueueRunner::SetupTransitionToTransferDst(VKRImage &img, VkImageMemor
|
||||
stage |= VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
|
||||
break;
|
||||
default:
|
||||
Crash();
|
||||
_dbg_assert_msg_(G3D, false, "Transition from this layout to transfer dst not supported (%d)", (int)img.layout);
|
||||
break;
|
||||
}
|
||||
barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||
barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
|
||||
@@ -869,7 +875,8 @@ void VulkanQueueRunner::PerformReadback(const VKRStep &step, VkCommandBuffer cmd
|
||||
srcImage = &step.readback.src->depth;
|
||||
}
|
||||
else {
|
||||
assert(false);
|
||||
_dbg_assert_msg_(G3D, false, "No image aspect to readback?");
|
||||
return;
|
||||
}
|
||||
|
||||
VkImageMemoryBarrier barrier{ VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER };
|
||||
|
||||
@@ -690,6 +690,12 @@ VkImageView VulkanRenderManager::BindFramebufferAsTexture(VKRFramebuffer *fb, in
|
||||
}
|
||||
}
|
||||
|
||||
if (!curRenderStep_->preTransitions.empty() &&
|
||||
curRenderStep_->preTransitions.back().fb == fb &&
|
||||
curRenderStep_->preTransitions.back().targetLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) {
|
||||
// We're done.
|
||||
return fb->color.imageView;
|
||||
}
|
||||
curRenderStep_->preTransitions.push_back({ fb, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL });
|
||||
return fb->color.imageView;
|
||||
}
|
||||
|
||||
@@ -51,13 +51,20 @@ public:
|
||||
}
|
||||
|
||||
~VKRFramebuffer() {
|
||||
vulkan_->Delete().QueueDeleteImage(color.image);
|
||||
vulkan_->Delete().QueueDeleteImage(depth.image);
|
||||
vulkan_->Delete().QueueDeleteImageView(color.imageView);
|
||||
vulkan_->Delete().QueueDeleteImageView(depth.imageView);
|
||||
vulkan_->Delete().QueueDeleteDeviceMemory(color.memory);
|
||||
vulkan_->Delete().QueueDeleteDeviceMemory(depth.memory);
|
||||
vulkan_->Delete().QueueDeleteFramebuffer(framebuf);
|
||||
if (color.image)
|
||||
vulkan_->Delete().QueueDeleteImage(color.image);
|
||||
if (depth.image)
|
||||
vulkan_->Delete().QueueDeleteImage(depth.image);
|
||||
if (color.imageView)
|
||||
vulkan_->Delete().QueueDeleteImageView(color.imageView);
|
||||
if (depth.imageView)
|
||||
vulkan_->Delete().QueueDeleteImageView(depth.imageView);
|
||||
if (color.memory)
|
||||
vulkan_->Delete().QueueDeleteDeviceMemory(color.memory);
|
||||
if (depth.memory)
|
||||
vulkan_->Delete().QueueDeleteDeviceMemory(depth.memory);
|
||||
if (framebuf)
|
||||
vulkan_->Delete().QueueDeleteFramebuffer(framebuf);
|
||||
}
|
||||
|
||||
int numShadows = 1; // TODO: Support this.
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include "base/logging.h"
|
||||
#include "thin3d/thin3d.h"
|
||||
#include "Common/Log.h"
|
||||
#include "Common/ColorConv.h"
|
||||
|
||||
namespace Draw {
|
||||
@@ -75,11 +76,26 @@ bool RefCountedObject::Release() {
|
||||
}
|
||||
}
|
||||
else {
|
||||
_dbg_assert_msg_(G3D, false, "Refcount (%d) invalid for object %p - corrupt?", refcount_, this);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool RefCountedObject::ReleaseAssertLast() {
|
||||
_dbg_assert_msg_(G3D, refcount_ == 1, "RefCountedObject: Expected to be the last reference, but isn't!");
|
||||
if (refcount_ > 0 && refcount_ < 10000) {
|
||||
refcount_--;
|
||||
if (refcount_ == 0) {
|
||||
delete this;
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
ELOG("Refcount (%d) invalid for object %p - corrupt?", refcount_, this);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// ================================== PIXEL/FRAGMENT SHADERS
|
||||
|
||||
// The Vulkan ones can be re-used with modern GL later if desired, as they're just GLSL.
|
||||
|
||||
@@ -346,6 +346,7 @@ public:
|
||||
|
||||
void AddRef() { refcount_++; }
|
||||
bool Release();
|
||||
bool ReleaseAssertLast();
|
||||
|
||||
private:
|
||||
int refcount_;
|
||||
|
||||
@@ -1298,7 +1298,6 @@ uint32_t VKContext::GetDataFormatSupport(DataFormat fmt) const {
|
||||
// use this frame's init command buffer.
|
||||
class VKFramebuffer : public Framebuffer {
|
||||
public:
|
||||
// Inherits ownership so no AddRef.
|
||||
VKFramebuffer(VKRFramebuffer *fb) : buf_(fb) {}
|
||||
~VKFramebuffer() {
|
||||
buf_->vulkan_->Delete().QueueCallback([](void *fb) {
|
||||
|
||||
@@ -264,7 +264,7 @@ private:
|
||||
const char *category_;
|
||||
ScreenManager *screenManager_;
|
||||
std::string valueText_;
|
||||
bool restoreFocus_;
|
||||
bool restoreFocus_ = false;
|
||||
std::set<int> hidden_;
|
||||
};
|
||||
|
||||
|
||||
@@ -1314,8 +1314,10 @@ EventReturn ListView::OnItemCallback(int num, EventParams &e) {
|
||||
View *focused = GetFocusedView();
|
||||
OnChoice.Trigger(ev);
|
||||
CreateAllItems();
|
||||
if (focused)
|
||||
SetFocusedView(e.v);
|
||||
// TODO: At this point, focused may no longer exist, depending on what OnChoice.Trigger does.
|
||||
// Disable the refocus feature for now.
|
||||
// if (focused)
|
||||
// SetFocusedView(e.v);
|
||||
return EVENT_DONE;
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user