diff --git a/Common/BitScan.h b/Common/BitScan.h new file mode 100644 index 0000000000..729c320759 --- /dev/null +++ b/Common/BitScan.h @@ -0,0 +1,36 @@ +#pragma once + +#include "ppsspp_config.h" + +#if PPSSPP_PLATFORM(WINDOWS) +#include "Common/CommonWindows.h" + +// Use this if you know the value is non-zero. +inline uint32_t clz32_nonzero(uint32_t value) { + DWORD index; + BitScanReverse(&index, value); + return 31 ^ (uint32_t)index; +} + +inline uint32_t clz32(uint32_t value) { + if (!value) + return 32; + DWORD index; + BitScanReverse(&index, value); + return 31 ^ (uint32_t)index; +} + +#else + +// Use this if you know the value is non-zero. +inline uint32_t clz32_nonzero(uint32_t value) { + return __builtin_clz(value); +} + +inline uint32_t clz32(uint32_t value) { + if (!value) + return 32; + return __builtin_clz(value); +} + +#endif diff --git a/Common/Common.vcxproj b/Common/Common.vcxproj index 226295fa38..7cd6bb9e56 100644 --- a/Common/Common.vcxproj +++ b/Common/Common.vcxproj @@ -128,7 +128,6 @@ - @@ -384,6 +383,7 @@ + diff --git a/Common/Common.vcxproj.filters b/Common/Common.vcxproj.filters index bad1776855..68e7c01282 100644 --- a/Common/Common.vcxproj.filters +++ b/Common/Common.vcxproj.filters @@ -73,6 +73,7 @@ + @@ -149,4 +150,4 @@ {c14d66ef-5f7c-4565-975a-72774e7ccfb9} - + \ No newline at end of file diff --git a/Core/MIPS/IR/IRInterpreter.cpp b/Core/MIPS/IR/IRInterpreter.cpp index 51724a80ef..13753c78ac 100644 --- a/Core/MIPS/IR/IRInterpreter.cpp +++ b/Core/MIPS/IR/IRInterpreter.cpp @@ -4,6 +4,7 @@ #include "ppsspp_config.h" #include "math/math_util.h" #include "Common/Common.h" +#include "Common/BitScan.h" #ifdef _M_SSE #include @@ -563,14 +564,7 @@ u32 IRInterpret(MIPSState *mips, const IRInst *inst, int count) { case IROp::Clz: { - int x = 31; - int count = 0; - int value = mips->r[inst->src1]; - while (x >= 0 && !(value & (1 << x))) { - count++; - x--; - } - mips->r[inst->dest] = count; + mips->r[inst->dest] = clz32(mips->r[inst->src1]); break; } diff --git a/Core/MIPS/MIPSInt.cpp b/Core/MIPS/MIPSInt.cpp index 0c29cccdae..903386a08e 100644 --- a/Core/MIPS/MIPSInt.cpp +++ b/Core/MIPS/MIPSInt.cpp @@ -15,13 +15,12 @@ // Official git repository and contact information can be found at // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. -// MIPS is really trivial :) - #include #include "math/math_util.h" #include "Common/Common.h" +#include "Common/BitScan.h" #include "Core/Config.h" #include "Core/Core.h" #include "Core/Host.h" @@ -281,7 +280,6 @@ namespace MIPSInt switch (op & 0x3f) { case 8: //jr - // LOG(CPU,"returning from: %08x",PC); DelayBranchTo(addr); break; case 9: //jalr @@ -551,28 +549,10 @@ namespace MIPSInt switch (op & 63) { case 22: //clz - { //TODO: verify - int x = 31; - int count=0; - while (x >= 0 && !(R(rs) & (1<= 0 && (R(rs) & (1<> 16) & 0xF) { case 3: { @@ -363,6 +363,9 @@ namespace MIPSInt case 7: sprefixAdd = VFPU_MAKE_CONSTANTS(VFPUConst::ONE, VFPUConst::ONE, VFPUConst::ONE, VFPUConst::ONE); break; + default: + _dbg_assert_msg_(CPU, 0, "Unknown matrix init op"); + break; } ApplyPrefixST(&prefixed[off * 4], VFPURewritePrefix(VFPU_CTRL_SPREFIX, sprefixRemove, sprefixAdd), V_Quad); WriteMatrix(prefixed, sz, vd); @@ -1559,7 +1562,7 @@ namespace MIPSInt int vd = _VD; int vs = _VS; int vt = _VT; - int ins = (op >> 23) & 7; + int ins = (op >> 23) & 3; VectorSize sz = (VectorSize)(ins + 1); MatrixSize msz = (MatrixSize)(ins + 1); @@ -1598,9 +1601,13 @@ namespace MIPSInt VFPUConst constZ = n < 3 ? VFPUConst::ZERO : VFPUConst::NONE; VFPUConst constW = n < 4 ? VFPUConst::ZERO : VFPUConst::NONE; if (ins >= n) { - constY = ins == 1 ? VFPUConst::ONE : VFPUConst::ZERO; - constZ = ins == 2 ? VFPUConst::ONE : VFPUConst::ZERO; - constW = ins == 3 ? VFPUConst::ONE : VFPUConst::ZERO; + if (ins == 1) { + constY = VFPUConst::ONE; + } else if (ins == 2) { + constZ = VFPUConst::ONE; + } else if (ins == 3) { + constW = VFPUConst::ONE; + } } u32 tprefixRemove = VFPU_SWIZZLE(0, n < 2 ? 3 : 0, n < 3 ? 3 : 0, n < 4 ? 3 : 0); u32 tprefixAdd = VFPU_MAKE_CONSTANTS(constX, constY, constZ, constW); diff --git a/Core/Screenshot.cpp b/Core/Screenshot.cpp index 46694c35a1..2a2ddcf27c 100644 --- a/Core/Screenshot.cpp +++ b/Core/Screenshot.cpp @@ -237,26 +237,24 @@ static bool ConvertPixelTo8888RGBA(GPUDebugBufferFormat fmt, u8 &r, u8 &g, u8 &b } const u8 *ConvertBufferToScreenshot(const GPUDebugBuffer &buf, bool alpha, u8 *&temp, u32 &w, u32 &h) { - int pixelSize = alpha ? 4 : 3; + size_t pixelSize = alpha ? 4 : 3; GPUDebugBufferFormat nativeFmt = alpha ? GPU_DBG_FORMAT_8888 : GPU_DBG_FORMAT_888_RGB; w = std::min(w, buf.GetStride()); h = std::min(h, buf.GetHeight()); // The temp buffer will be freed by the caller if set, and can be the return value. - if (buf.GetFlipped() || buf.GetFormat() != nativeFmt) { - temp = new u8[pixelSize * w * h]; - } else { - temp = nullptr; - } + temp = nullptr; const u8 *buffer = buf.GetData(); if (buf.GetFlipped() && buf.GetFormat() == nativeFmt) { + temp = new u8[pixelSize * w * h]; // Silly OpenGL reads upside down, we flip to another buffer for simplicity. for (u32 y = 0; y < h; y++) { memcpy(temp + y * w * pixelSize, buffer + (buf.GetHeight() - y - 1) * buf.GetStride() * pixelSize, w * pixelSize); } } else if (buf.GetFormat() < GPU_DBG_FORMAT_FLOAT && buf.GetFormat() != nativeFmt) { + temp = new u8[pixelSize * w * h]; // Let's boil it down to how we need to interpret the bits. int baseFmt = buf.GetFormat() & ~(GPU_DBG_FORMAT_REVERSE_FLAG | GPU_DBG_FORMAT_BRSWAP_FLAG); bool rev = (buf.GetFormat() & GPU_DBG_FORMAT_REVERSE_FLAG) != 0; @@ -284,6 +282,7 @@ const u8 *ConvertBufferToScreenshot(const GPUDebugBuffer &buf, bool alpha, u8 *& } } } else if (buf.GetFormat() != nativeFmt) { + temp = new u8[pixelSize * w * h]; bool flip = buf.GetFlipped(); // This is pretty inefficient. diff --git a/GPU/Common/GPUDebugInterface.h b/GPU/Common/GPUDebugInterface.h index 0f9410dc3f..e56a349df1 100644 --- a/GPU/Common/GPUDebugInterface.h +++ b/GPU/Common/GPUDebugInterface.h @@ -79,7 +79,7 @@ inline GPUDebugBufferFormat &operator |=(GPUDebugBufferFormat &lhs, const GPUDeb } struct GPUDebugBuffer { - GPUDebugBuffer() : alloc_(false), data_(NULL) { + GPUDebugBuffer() { } GPUDebugBuffer(void *data, u32 stride, u32 height, GEBufferFormat fmt, bool reversed = false) @@ -100,7 +100,7 @@ struct GPUDebugBuffer { : alloc_(false), data_((u8 *)data), stride_(stride), height_(height), fmt_(fmt), flipped_(false) { } - GPUDebugBuffer(GPUDebugBuffer &&other) { + GPUDebugBuffer(GPUDebugBuffer &&other) noexcept { alloc_ = other.alloc_; data_ = other.data_; height_ = other.height_; @@ -108,14 +108,14 @@ struct GPUDebugBuffer { flipped_ = other.flipped_; fmt_ = other.fmt_; other.alloc_ = false; - other.data_ = NULL; + other.data_ = nullptr; } ~GPUDebugBuffer() { Free(); } - GPUDebugBuffer &operator = (GPUDebugBuffer &&other) { + GPUDebugBuffer &operator = (GPUDebugBuffer &&other) noexcept { if (this != &other) { Free(); alloc_ = other.alloc_; @@ -125,7 +125,7 @@ struct GPUDebugBuffer { flipped_ = other.flipped_; fmt_ = other.fmt_; other.alloc_ = false; - other.data_ = NULL; + other.data_ = nullptr; } return *this; @@ -164,12 +164,12 @@ struct GPUDebugBuffer { private: u32 PixelSize(GPUDebugBufferFormat fmt) const; - bool alloc_; - u8 *data_; - u32 stride_; - u32 height_; - GPUDebugBufferFormat fmt_; - bool flipped_; + bool alloc_ = false; + u8 *data_ = nullptr; + u32 stride_ = 0; + u32 height_ = 0; + GPUDebugBufferFormat fmt_ = GPU_DBG_FORMAT_INVALID; + bool flipped_ = false; }; struct GPUDebugVertex { diff --git a/ext/native/thin3d/VulkanQueueRunner.h b/ext/native/thin3d/VulkanQueueRunner.h index 911ef1ab0b..17f0acb69a 100644 --- a/ext/native/thin3d/VulkanQueueRunner.h +++ b/ext/native/thin3d/VulkanQueueRunner.h @@ -246,8 +246,8 @@ private: VulkanContext *vulkan_; - VkFramebuffer backbuffer_; - VkImage backbufferImage_; + VkFramebuffer backbuffer_ = VK_NULL_HANDLE; + VkImage backbufferImage_ = VK_NULL_HANDLE; VkRenderPass backbufferRenderPass_ = VK_NULL_HANDLE; VkRenderPass framebufferRenderPass_ = VK_NULL_HANDLE; diff --git a/ext/native/thin3d/VulkanRenderManager.cpp b/ext/native/thin3d/VulkanRenderManager.cpp index ddf44c0ebb..444d3111bb 100644 --- a/ext/native/thin3d/VulkanRenderManager.cpp +++ b/ext/native/thin3d/VulkanRenderManager.cpp @@ -159,7 +159,7 @@ void VulkanRenderManager::CreateBackbuffers() { VkCommandBuffer cmdInit = GetInitCmd(); for (uint32_t i = 0; i < swapchainImageCount_; i++) { - SwapchainImageData sc_buffer; + SwapchainImageData sc_buffer{}; sc_buffer.image = swapchainImages[i]; VkImageViewCreateInfo color_image_view = { VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO }; diff --git a/ext/native/thin3d/VulkanRenderManager.h b/ext/native/thin3d/VulkanRenderManager.h index cfac32d75c..84f7cbeed2 100644 --- a/ext/native/thin3d/VulkanRenderManager.h +++ b/ext/native/thin3d/VulkanRenderManager.h @@ -288,8 +288,8 @@ private: FrameData frameData_[VulkanContext::MAX_INFLIGHT_FRAMES]; // Submission time state - int curWidth_; - int curHeight_; + int curWidth_ = -1; + int curHeight_ = -1; bool insideFrame_ = false; VKRStep *curRenderStep_ = nullptr; std::vector steps_; @@ -310,7 +310,7 @@ private: }; std::vector framebuffers_; std::vector swapchainImages_; - uint32_t swapchainImageCount_; + uint32_t swapchainImageCount_ = 0; struct DepthBufferInfo { VkFormat format = VK_FORMAT_UNDEFINED; VkImage image = VK_NULL_HANDLE; diff --git a/ext/native/ui/ui_screen.h b/ext/native/ui/ui_screen.h index 99a6c486eb..c044e961a0 100644 --- a/ext/native/ui/ui_screen.h +++ b/ext/native/ui/ui_screen.h @@ -109,7 +109,7 @@ private: class ListPopupScreen : public PopupScreen { public: - ListPopupScreen(std::string title) : PopupScreen(title), showButtons_(false) {} + ListPopupScreen(std::string title) : PopupScreen(title) {} ListPopupScreen(std::string title, const std::vector &items, int selected, std::function callback, bool showButtons = false) : PopupScreen(title, "OK", "Cancel"), adaptor_(items, selected), callback_(callback), showButtons_(showButtons) { } @@ -135,13 +135,13 @@ protected: virtual bool ShowButtons() const override { return showButtons_; } virtual void CreatePopupContents(UI::ViewGroup *parent) override; UI::StringVectorListAdaptor adaptor_; - UI::ListView *listView_; + UI::ListView *listView_ = nullptr; private: UI::EventReturn OnListChoice(UI::EventParams &e); std::function callback_; - bool showButtons_; + bool showButtons_ = false; std::set hidden_; }; @@ -169,7 +169,7 @@ namespace UI { class SliderPopupScreen : public PopupScreen { public: SliderPopupScreen(int *value, int minValue, int maxValue, const std::string &title, int step = 1, const std::string &units = "") - : PopupScreen(title, "OK", "Cancel"), units_(units), value_(value), minValue_(minValue), maxValue_(maxValue), step_(step) {} + : PopupScreen(title, "OK", "Cancel"), units_(units), value_(value), minValue_(minValue), maxValue_(maxValue), step_(step) {} virtual void CreatePopupContents(ViewGroup *parent) override; void SetNegativeDisable(const std::string &str) { @@ -185,12 +185,12 @@ private: EventReturn OnTextChange(EventParams ¶ms); EventReturn OnSliderChange(EventParams ¶ms); virtual void OnCompleted(DialogResult result) override; - Slider *slider_; - UI::TextEdit *edit_; + Slider *slider_ = nullptr; + UI::TextEdit *edit_ = nullptr; std::string units_; std::string negativeLabel_; int *value_; - int sliderValue_; + int sliderValue_ = 0; int minValue_; int maxValue_; int step_; diff --git a/ext/native/ui/view.h b/ext/native/ui/view.h index 2ca22d1c38..45d0538d44 100644 --- a/ext/native/ui/view.h +++ b/ext/native/ui/view.h @@ -552,8 +552,8 @@ private: float paddingLeft_; float paddingRight_; int step_; - int repeat_; - int repeatCode_; + int repeat_ = 0; + int repeatCode_ = 0; }; class SliderFloat : public Clickable { @@ -580,7 +580,7 @@ private: float paddingLeft_; float paddingRight_; int repeat_; - int repeatCode_; + int repeatCode_ = 0; }; // Basic button that modifies a bitfield based on the pressed status. Supports multitouch. diff --git a/ext/native/util/text/wrap_text.h b/ext/native/util/text/wrap_text.h index 7418a8022e..61049bccef 100644 --- a/ext/native/util/text/wrap_text.h +++ b/ext/native/util/text/wrap_text.h @@ -31,7 +31,7 @@ protected: // Position the current word starts at. float x_ = 0.0f; // Most recent width of word since last index. - float wordWidth_; + float wordWidth_ = 0.0f; // Force the next word to cut partially and wrap. bool forceEarlyWrap_ = false; }; diff --git a/unittest/UnitTest.cpp b/unittest/UnitTest.cpp index 9fdf32f8cd..b07feb5bb2 100644 --- a/unittest/UnitTest.cpp +++ b/unittest/UnitTest.cpp @@ -31,6 +31,9 @@ #include #include +#include "Common/BitScan.h" +#include "Core/MIPS/MIPSVFPUUtils.h" + #include "base/NativeApp.h" #include "base/logging.h" #include "input/input_state.h" @@ -459,6 +462,29 @@ bool TestQuickTexHash() { return true; } +bool TestCLZ() { + static const uint32_t input[] = { + 0xFFFFFFFF, + 0x00FFFFF0, + 0x00101000, + 0x00003000, + 0x00000001, + 0x00000000, + }; + static const uint32_t expected[] = { + 0, + 8, + 11, + 18, + 31, + 32, + }; + for (int i = 0; i < ARRAY_SIZE(input); i++) { + EXPECT_EQ_INT(clz32(input[i]), expected[i]); + } + return true; +} + typedef bool (*TestFunc)(); struct TestItem { const char *name; @@ -491,6 +517,7 @@ TestItem availableTests[] = { TEST_ITEM(MatrixTranspose), TEST_ITEM(ParseLBN), TEST_ITEM(QuickTexHash), + TEST_ITEM(CLZ), }; int main(int argc, const char *argv[]) {