mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-11-13 01:29:41 +01:00
Merge pull request #15938 from hrydgard/misc-optimizations
Misc optimizations
This commit is contained in:
33 files changed
+219
-138
No files matched your search
@@ -43,6 +43,20 @@ struct TinySet {
|
||||
slowLookup_->push_back(t);
|
||||
return slowLookup_->back();
|
||||
}
|
||||
void append(const TinySet<T, MaxFastSize> &other) {
|
||||
size_t otherSize = other.size();
|
||||
if (size() + otherSize <= MaxFastSize) {
|
||||
// Fast case
|
||||
for (int i = 0; i < otherSize; i++) {
|
||||
fastLookup_[fastCount + i] = other.fastLookup_[i];
|
||||
}
|
||||
fastCount += other.fastCount;
|
||||
} else {
|
||||
for (int i = 0; i < otherSize; i++) {
|
||||
push_back(other[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
bool contains(T t) const {
|
||||
for (int i = 0; i < fastCount; i++) {
|
||||
if (fastLookup_[i] == t)
|
||||
@@ -79,7 +93,7 @@ struct TinySet {
|
||||
return fastCount == 0;
|
||||
}
|
||||
size_t size() const {
|
||||
if (fastCount <= MaxFastSize) {
|
||||
if (!slowLookup_) {
|
||||
return fastCount;
|
||||
} else {
|
||||
return slowLookup_->size() + MaxFastSize;
|
||||
@@ -92,6 +106,9 @@ struct TinySet {
|
||||
return (*slowLookup_)[index - MaxFastSize];
|
||||
}
|
||||
}
|
||||
const T &back() const {
|
||||
return (*this)[size() - 1];
|
||||
}
|
||||
|
||||
private:
|
||||
void insertSlow(T t) {
|
||||
|
||||
@@ -347,6 +347,7 @@ void VulkanQueueRunner::RunSteps(VkCommandBuffer cmd, std::vector<VKRStep *> &st
|
||||
profile->cpuStartTime = time_now_d();
|
||||
|
||||
bool emitLabels = vulkan_->Extensions().EXT_debug_utils;
|
||||
|
||||
for (size_t i = 0; i < steps.size(); i++) {
|
||||
const VKRStep &step = *steps[i];
|
||||
|
||||
@@ -685,7 +686,7 @@ void VulkanQueueRunner::ApplyRenderPassMerge(std::vector<VKRStep *> &steps) {
|
||||
auto mergeRenderSteps = [](VKRStep *dst, VKRStep *src) {
|
||||
// OK. Now, if it's a render, slurp up all the commands and kill the step.
|
||||
// Also slurp up any pretransitions.
|
||||
dst->preTransitions.insert(dst->preTransitions.end(), src->preTransitions.begin(), src->preTransitions.end());
|
||||
dst->preTransitions.append(src->preTransitions);
|
||||
dst->commands.insert(dst->commands.end(), src->commands.begin(), src->commands.end());
|
||||
MergeRenderAreaRectInto(&dst->render.renderArea, src->render.renderArea);
|
||||
// So we don't consider it for other things, maybe doesn't matter.
|
||||
@@ -1060,7 +1061,8 @@ void TransitionFromOptimal(VkCommandBuffer cmd, VkImage colorImage, VkImageLayou
|
||||
}
|
||||
|
||||
void VulkanQueueRunner::PerformRenderPass(const VKRStep &step, VkCommandBuffer cmd) {
|
||||
for (const auto &iter : step.preTransitions) {
|
||||
for (size_t i = 0; i < step.preTransitions.size(); i++) {
|
||||
const TransitionRequest &iter = step.preTransitions[i];
|
||||
if (iter.aspect == VK_IMAGE_ASPECT_COLOR_BIT && iter.fb->color.layout != iter.targetLayout) {
|
||||
recordBarrier_.TransitionImageAuto(
|
||||
iter.fb->color.image,
|
||||
@@ -1151,6 +1153,8 @@ void VulkanQueueRunner::PerformRenderPass(const VKRStep &step, VkCommandBuffer c
|
||||
// The stencil ones are very commonly mostly redundant so let's eliminate them where possible.
|
||||
// Might also want to consider scissor and viewport.
|
||||
VkPipeline lastPipeline = VK_NULL_HANDLE;
|
||||
VkPipelineLayout pipelineLayout = VK_NULL_HANDLE;
|
||||
|
||||
int lastStencilWriteMask = -1;
|
||||
int lastStencilCompareMask = -1;
|
||||
int lastStencilReference = -1;
|
||||
@@ -1166,6 +1170,7 @@ void VulkanQueueRunner::PerformRenderPass(const VKRStep &step, VkCommandBuffer c
|
||||
VkPipeline pipeline = c.pipeline.pipeline;
|
||||
if (pipeline != lastGraphicsPipeline) {
|
||||
vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
|
||||
pipelineLayout = c.pipeline.pipelineLayout;
|
||||
lastGraphicsPipeline = pipeline;
|
||||
// Reset dynamic state so it gets refreshed with the new pipeline.
|
||||
lastStencilWriteMask = -1;
|
||||
@@ -1187,6 +1192,7 @@ void VulkanQueueRunner::PerformRenderPass(const VKRStep &step, VkCommandBuffer c
|
||||
}
|
||||
if (pipeline->pipeline != lastGraphicsPipeline && pipeline->pipeline != VK_NULL_HANDLE) {
|
||||
vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->pipeline);
|
||||
pipelineLayout = c.pipeline.pipelineLayout;
|
||||
lastGraphicsPipeline = pipeline->pipeline;
|
||||
// Reset dynamic state so it gets refreshed with the new pipeline.
|
||||
lastStencilWriteMask = -1;
|
||||
@@ -1208,6 +1214,7 @@ void VulkanQueueRunner::PerformRenderPass(const VKRStep &step, VkCommandBuffer c
|
||||
}
|
||||
if (pipeline->pipeline != lastComputePipeline && pipeline->pipeline != VK_NULL_HANDLE) {
|
||||
vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline->pipeline);
|
||||
pipelineLayout = c.pipeline.pipelineLayout;
|
||||
lastComputePipeline = pipeline->pipeline;
|
||||
}
|
||||
break;
|
||||
@@ -1257,7 +1264,7 @@ void VulkanQueueRunner::PerformRenderPass(const VKRStep &step, VkCommandBuffer c
|
||||
}
|
||||
|
||||
case VKRRenderCommand::PUSH_CONSTANTS:
|
||||
vkCmdPushConstants(cmd, c.push.pipelineLayout, c.push.stages, c.push.offset, c.push.size, c.push.data);
|
||||
vkCmdPushConstants(cmd, pipelineLayout, c.push.stages, c.push.offset, c.push.size, c.push.data);
|
||||
break;
|
||||
|
||||
case VKRRenderCommand::STENCIL:
|
||||
@@ -1276,14 +1283,17 @@ void VulkanQueueRunner::PerformRenderPass(const VKRStep &step, VkCommandBuffer c
|
||||
break;
|
||||
|
||||
case VKRRenderCommand::DRAW_INDEXED:
|
||||
vkCmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, c.drawIndexed.pipelineLayout, 0, 1, &c.drawIndexed.ds, c.drawIndexed.numUboOffsets, c.drawIndexed.uboOffsets);
|
||||
vkCmdBindIndexBuffer(cmd, c.drawIndexed.ibuffer, c.drawIndexed.ioffset, c.drawIndexed.indexType);
|
||||
vkCmdBindVertexBuffers(cmd, 0, 1, &c.drawIndexed.vbuffer, &c.drawIndexed.voffset);
|
||||
{
|
||||
vkCmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &c.drawIndexed.ds, c.drawIndexed.numUboOffsets, c.drawIndexed.uboOffsets);
|
||||
vkCmdBindIndexBuffer(cmd, c.drawIndexed.ibuffer, c.drawIndexed.ioffset, (VkIndexType)c.drawIndexed.indexType);
|
||||
VkDeviceSize voffset = c.drawIndexed.voffset;
|
||||
vkCmdBindVertexBuffers(cmd, 0, 1, &c.drawIndexed.vbuffer, &voffset);
|
||||
vkCmdDrawIndexed(cmd, c.drawIndexed.count, c.drawIndexed.instances, 0, 0, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
case VKRRenderCommand::DRAW:
|
||||
vkCmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, c.draw.pipelineLayout, 0, 1, &c.draw.ds, c.draw.numUboOffsets, c.draw.uboOffsets);
|
||||
vkCmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &c.draw.ds, c.draw.numUboOffsets, c.draw.uboOffsets);
|
||||
if (c.draw.vbuffer) {
|
||||
vkCmdBindVertexBuffers(cmd, 0, 1, &c.draw.vbuffer, &c.draw.voffset);
|
||||
}
|
||||
|
||||
@@ -52,15 +52,17 @@ struct VkRenderData {
|
||||
union {
|
||||
struct {
|
||||
VkPipeline pipeline;
|
||||
VkPipelineLayout pipelineLayout;
|
||||
} pipeline;
|
||||
struct {
|
||||
VKRGraphicsPipeline *pipeline;
|
||||
VkPipelineLayout pipelineLayout;
|
||||
} graphics_pipeline;
|
||||
struct {
|
||||
VKRComputePipeline *pipeline;
|
||||
VkPipelineLayout pipelineLayout;
|
||||
} compute_pipeline;
|
||||
struct {
|
||||
VkPipelineLayout pipelineLayout;
|
||||
VkDescriptorSet ds;
|
||||
int numUboOffsets;
|
||||
uint32_t uboOffsets[3];
|
||||
@@ -70,17 +72,16 @@ struct VkRenderData {
|
||||
uint32_t offset;
|
||||
} draw;
|
||||
struct {
|
||||
VkPipelineLayout pipelineLayout;
|
||||
VkDescriptorSet ds;
|
||||
int numUboOffsets;
|
||||
uint32_t uboOffsets[3];
|
||||
VkBuffer vbuffer; // might need to increase at some point
|
||||
VkDeviceSize voffset;
|
||||
VkBuffer ibuffer;
|
||||
VkDeviceSize ioffset;
|
||||
uint32_t voffset;
|
||||
uint32_t ioffset;
|
||||
uint32_t count;
|
||||
int16_t instances;
|
||||
VkIndexType indexType;
|
||||
int16_t indexType;
|
||||
} drawIndexed;
|
||||
struct {
|
||||
uint32_t clearColor;
|
||||
@@ -103,7 +104,6 @@ struct VkRenderData {
|
||||
uint32_t color;
|
||||
} blendColor;
|
||||
struct {
|
||||
VkPipelineLayout pipelineLayout;
|
||||
VkShaderStageFlags stages;
|
||||
uint8_t offset;
|
||||
uint8_t size;
|
||||
@@ -134,8 +134,8 @@ enum class VKRRenderPassStoreAction : uint8_t {
|
||||
};
|
||||
|
||||
struct TransitionRequest {
|
||||
VkImageAspectFlags aspect; // COLOR or DEPTH
|
||||
VKRFramebuffer *fb;
|
||||
VkImageAspectFlags aspect; // COLOR or DEPTH
|
||||
VkImageLayout targetLayout;
|
||||
};
|
||||
|
||||
@@ -153,7 +153,7 @@ struct VKRStep {
|
||||
|
||||
VKRStepType stepType;
|
||||
std::vector<VkRenderData> commands;
|
||||
std::vector<TransitionRequest> preTransitions;
|
||||
TinySet<TransitionRequest, 4> preTransitions;
|
||||
TinySet<VKRFramebuffer *, 8> dependencies;
|
||||
const char *tag;
|
||||
union {
|
||||
|
||||
@@ -1189,7 +1189,7 @@ VkImageView VulkanRenderManager::BindFramebufferAsTexture(VKRFramebuffer *fb, in
|
||||
// We're done.
|
||||
return aspectBit == VK_IMAGE_ASPECT_COLOR_BIT ? fb->color.imageView : fb->depth.depthSampleView;
|
||||
} else {
|
||||
curRenderStep_->preTransitions.push_back({ aspectBit, fb, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL });
|
||||
curRenderStep_->preTransitions.push_back({ fb, aspectBit, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL });
|
||||
return aspectBit == VK_IMAGE_ASPECT_COLOR_BIT ? fb->color.imageView : fb->depth.depthSampleView;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -242,29 +242,32 @@ public:
|
||||
return pipeline;
|
||||
}
|
||||
|
||||
void BindPipeline(VkPipeline pipeline, PipelineFlags flags) {
|
||||
void BindPipeline(VkPipeline pipeline, PipelineFlags flags, VkPipelineLayout pipelineLayout) {
|
||||
_dbg_assert_(curRenderStep_ && curRenderStep_->stepType == VKRStepType::RENDER);
|
||||
_dbg_assert_(pipeline != VK_NULL_HANDLE);
|
||||
VkRenderData data{ VKRRenderCommand::BIND_PIPELINE };
|
||||
data.pipeline.pipeline = pipeline;
|
||||
data.pipeline.pipelineLayout = pipelineLayout;
|
||||
curPipelineFlags_ |= flags;
|
||||
curRenderStep_->commands.push_back(data);
|
||||
}
|
||||
|
||||
void BindPipeline(VKRGraphicsPipeline *pipeline, PipelineFlags flags) {
|
||||
void BindPipeline(VKRGraphicsPipeline *pipeline, PipelineFlags flags, VkPipelineLayout pipelineLayout) {
|
||||
_dbg_assert_(curRenderStep_ && curRenderStep_->stepType == VKRStepType::RENDER);
|
||||
_dbg_assert_(pipeline != nullptr);
|
||||
VkRenderData data{ VKRRenderCommand::BIND_GRAPHICS_PIPELINE };
|
||||
data.graphics_pipeline.pipeline = pipeline;
|
||||
data.graphics_pipeline.pipelineLayout = pipelineLayout;
|
||||
curPipelineFlags_ |= flags;
|
||||
curRenderStep_->commands.push_back(data);
|
||||
}
|
||||
|
||||
void BindPipeline(VKRComputePipeline *pipeline, PipelineFlags flags) {
|
||||
void BindPipeline(VKRComputePipeline *pipeline, PipelineFlags flags, VkPipelineLayout pipelineLayout) {
|
||||
_dbg_assert_(curRenderStep_ && curRenderStep_->stepType == VKRStepType::RENDER);
|
||||
_dbg_assert_(pipeline != nullptr);
|
||||
VkRenderData data{ VKRRenderCommand::BIND_COMPUTE_PIPELINE };
|
||||
data.compute_pipeline.pipeline = pipeline;
|
||||
data.compute_pipeline.pipelineLayout = pipelineLayout;
|
||||
curPipelineFlags_ |= flags;
|
||||
curRenderStep_->commands.push_back(data);
|
||||
}
|
||||
@@ -351,7 +354,6 @@ public:
|
||||
_dbg_assert_(curRenderStep_ && curRenderStep_->stepType == VKRStepType::RENDER);
|
||||
_dbg_assert_(size + offset < 40);
|
||||
VkRenderData data{ VKRRenderCommand::PUSH_CONSTANTS };
|
||||
data.push.pipelineLayout = pipelineLayout;
|
||||
data.push.stages = stages;
|
||||
data.push.offset = offset;
|
||||
data.push.size = size;
|
||||
@@ -386,12 +388,11 @@ public:
|
||||
curRenderStep_->render.stencilStore = VKRRenderPassStoreAction::DONT_CARE;
|
||||
}
|
||||
|
||||
void Draw(VkPipelineLayout layout, VkDescriptorSet descSet, int numUboOffsets, const uint32_t *uboOffsets, VkBuffer vbuffer, int voffset, int count, int offset = 0) {
|
||||
void Draw(VkDescriptorSet descSet, int numUboOffsets, const uint32_t *uboOffsets, VkBuffer vbuffer, int voffset, int count, int offset = 0) {
|
||||
_dbg_assert_(curRenderStep_ && curRenderStep_->stepType == VKRStepType::RENDER && curStepHasViewport_ && curStepHasScissor_);
|
||||
VkRenderData data{ VKRRenderCommand::DRAW };
|
||||
data.draw.count = count;
|
||||
data.draw.offset = offset;
|
||||
data.draw.pipelineLayout = layout;
|
||||
data.draw.ds = descSet;
|
||||
data.draw.vbuffer = vbuffer;
|
||||
data.draw.voffset = voffset;
|
||||
@@ -403,12 +404,11 @@ public:
|
||||
curRenderStep_->render.numDraws++;
|
||||
}
|
||||
|
||||
void DrawIndexed(VkPipelineLayout layout, VkDescriptorSet descSet, int numUboOffsets, const uint32_t *uboOffsets, VkBuffer vbuffer, int voffset, VkBuffer ibuffer, int ioffset, int count, int numInstances, VkIndexType indexType) {
|
||||
void DrawIndexed(VkDescriptorSet descSet, int numUboOffsets, const uint32_t *uboOffsets, VkBuffer vbuffer, int voffset, VkBuffer ibuffer, int ioffset, int count, int numInstances, VkIndexType indexType) {
|
||||
_dbg_assert_(curRenderStep_ && curRenderStep_->stepType == VKRStepType::RENDER && curStepHasViewport_ && curStepHasScissor_);
|
||||
VkRenderData data{ VKRRenderCommand::DRAW_INDEXED };
|
||||
data.drawIndexed.count = count;
|
||||
data.drawIndexed.instances = numInstances;
|
||||
data.drawIndexed.pipelineLayout = layout;
|
||||
data.drawIndexed.ds = descSet;
|
||||
data.drawIndexed.vbuffer = vbuffer;
|
||||
data.drawIndexed.voffset = voffset;
|
||||
|
||||
@@ -1339,7 +1339,7 @@ void VKContext::Draw(int vertexCount, int offset) {
|
||||
|
||||
BindCompatiblePipeline();
|
||||
ApplyDynamicState();
|
||||
renderManager_.Draw(pipelineLayout_, descSet, 1, &ubo_offset, vulkanVbuf, (int)vbBindOffset + curVBufferOffsets_[0], vertexCount, offset);
|
||||
renderManager_.Draw(descSet, 1, &ubo_offset, vulkanVbuf, (int)vbBindOffset + curVBufferOffsets_[0], vertexCount, offset);
|
||||
}
|
||||
|
||||
void VKContext::DrawIndexed(int vertexCount, int offset) {
|
||||
@@ -1359,7 +1359,7 @@ void VKContext::DrawIndexed(int vertexCount, int offset) {
|
||||
|
||||
BindCompatiblePipeline();
|
||||
ApplyDynamicState();
|
||||
renderManager_.DrawIndexed(pipelineLayout_, descSet, 1, &ubo_offset, vulkanVbuf, (int)vbBindOffset + curVBufferOffsets_[0], vulkanIbuf, (int)ibBindOffset + offset * sizeof(uint32_t), vertexCount, 1, VK_INDEX_TYPE_UINT16);
|
||||
renderManager_.DrawIndexed(descSet, 1, &ubo_offset, vulkanVbuf, (int)vbBindOffset + curVBufferOffsets_[0], vulkanIbuf, (int)ibBindOffset + offset * sizeof(uint32_t), vertexCount, 1, VK_INDEX_TYPE_UINT16);
|
||||
}
|
||||
|
||||
void VKContext::DrawUP(const void *vdata, int vertexCount) {
|
||||
@@ -1375,15 +1375,15 @@ void VKContext::DrawUP(const void *vdata, int vertexCount) {
|
||||
|
||||
BindCompatiblePipeline();
|
||||
ApplyDynamicState();
|
||||
renderManager_.Draw(pipelineLayout_, descSet, 1, &ubo_offset, vulkanVbuf, (int)vbBindOffset + curVBufferOffsets_[0], vertexCount);
|
||||
renderManager_.Draw(descSet, 1, &ubo_offset, vulkanVbuf, (int)vbBindOffset + curVBufferOffsets_[0], vertexCount);
|
||||
}
|
||||
|
||||
void VKContext::BindCompatiblePipeline() {
|
||||
VkRenderPass renderPass = renderManager_.GetCompatibleRenderPass();
|
||||
if (renderPass == renderManager_.GetBackbufferRenderPass()) {
|
||||
renderManager_.BindPipeline(curPipeline_->backbufferPipeline, curPipeline_->flags);
|
||||
renderManager_.BindPipeline(curPipeline_->backbufferPipeline, curPipeline_->flags, pipelineLayout_);
|
||||
} else {
|
||||
renderManager_.BindPipeline(curPipeline_->framebufferPipeline, curPipeline_->flags);
|
||||
renderManager_.BindPipeline(curPipeline_->framebufferPipeline, curPipeline_->flags, pipelineLayout_);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -44,15 +44,16 @@
|
||||
#include "Common/Buffer.h"
|
||||
#include "Common/StringUtils.h"
|
||||
|
||||
void truncate_cpy(char *dest, size_t destSize, const char *src) {
|
||||
size_t truncate_cpy(char *dest, size_t destSize, const char *src) {
|
||||
size_t len = strlen(src);
|
||||
if (len >= destSize - 1) {
|
||||
memcpy(dest, src, destSize - 1);
|
||||
dest[destSize - 1] = '\0';
|
||||
len = destSize - 1;
|
||||
} else {
|
||||
memcpy(dest, src, len);
|
||||
dest[len] = '\0';
|
||||
}
|
||||
dest[len] = '\0';
|
||||
return len;
|
||||
}
|
||||
|
||||
const char* safe_string(const char* s) {
|
||||
|
||||
@@ -78,10 +78,10 @@ std::string ReplaceAll(std::string input, const std::string& src, const std::str
|
||||
|
||||
void SkipSpace(const char **ptr);
|
||||
|
||||
void truncate_cpy(char *dest, size_t destSize, const char *src);
|
||||
size_t truncate_cpy(char *dest, size_t destSize, const char *src);
|
||||
template<size_t Count>
|
||||
inline void truncate_cpy(char(&out)[Count], const char *src) {
|
||||
truncate_cpy(out, Count, src);
|
||||
inline size_t truncate_cpy(char(&out)[Count], const char *src) {
|
||||
return truncate_cpy(out, Count, src);
|
||||
}
|
||||
|
||||
const char* safe_string(const char* s);
|
||||
|
||||
@@ -37,7 +37,8 @@ public:
|
||||
|
||||
bool Mark(uint32_t addr, uint32_t size, uint64_t ticks, uint32_t pc, bool allocated, const char *tag);
|
||||
bool Find(MemBlockFlags flags, uint32_t addr, uint32_t size, std::vector<MemBlockInfo> &results);
|
||||
bool FastFindWriteTag(MemBlockFlags flags, uint32_t addr, uint32_t size, std::string &result);
|
||||
// Note that the returned pointer gets invalidated as soon as Mark is called.
|
||||
const char *FastFindWriteTag(MemBlockFlags flags, uint32_t addr, uint32_t size);
|
||||
void Reset();
|
||||
void DoState(PointerWrap &p);
|
||||
|
||||
@@ -151,17 +152,16 @@ bool MemSlabMap::Find(MemBlockFlags flags, uint32_t addr, uint32_t size, std::ve
|
||||
return found;
|
||||
}
|
||||
|
||||
bool MemSlabMap::FastFindWriteTag(MemBlockFlags flags, uint32_t addr, uint32_t size, std::string &result) {
|
||||
const char *MemSlabMap::FastFindWriteTag(MemBlockFlags flags, uint32_t addr, uint32_t size) {
|
||||
uint32_t end = addr + size;
|
||||
Slab *slab = FindSlab(addr);
|
||||
while (slab != nullptr && slab->start < end) {
|
||||
if (slab->pc != 0 || slab->tag[0] != '\0') {
|
||||
result = slab->tag;
|
||||
return true;
|
||||
return slab->tag;
|
||||
}
|
||||
slab = slab->next;
|
||||
}
|
||||
return false;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void MemSlabMap::Reset() {
|
||||
@@ -485,7 +485,7 @@ std::vector<MemBlockInfo> FindMemInfoByFlag(MemBlockFlags flags, uint32_t start,
|
||||
return results;
|
||||
}
|
||||
|
||||
static std::string FindWriteTagByFlag(MemBlockFlags flags, uint32_t start, uint32_t size) {
|
||||
static const char *FindWriteTagByFlag(MemBlockFlags flags, uint32_t start, uint32_t size) {
|
||||
start &= ~0xC0000000;
|
||||
|
||||
if (pendingNotifyMinAddr1 < start + size && pendingNotifyMaxAddr1 >= start)
|
||||
@@ -493,37 +493,51 @@ static std::string FindWriteTagByFlag(MemBlockFlags flags, uint32_t start, uint3
|
||||
if (pendingNotifyMinAddr2 < start + size && pendingNotifyMaxAddr2 >= start)
|
||||
FlushPendingMemInfo();
|
||||
|
||||
std::string tag;
|
||||
if (flags & MemBlockFlags::ALLOC) {
|
||||
if (allocMap.FastFindWriteTag(MemBlockFlags::ALLOC, start, size, tag))
|
||||
const char *tag = allocMap.FastFindWriteTag(MemBlockFlags::ALLOC, start, size);
|
||||
if (tag)
|
||||
return tag;
|
||||
}
|
||||
if (flags & MemBlockFlags::SUB_ALLOC) {
|
||||
if (suballocMap.FastFindWriteTag(MemBlockFlags::SUB_ALLOC, start, size, tag))
|
||||
const char *tag = suballocMap.FastFindWriteTag(MemBlockFlags::SUB_ALLOC, start, size);
|
||||
if (tag)
|
||||
return tag;
|
||||
}
|
||||
if (flags & MemBlockFlags::WRITE) {
|
||||
if (writeMap.FastFindWriteTag(MemBlockFlags::WRITE, start, size, tag))
|
||||
const char *tag = writeMap.FastFindWriteTag(MemBlockFlags::WRITE, start, size);
|
||||
if (tag)
|
||||
return tag;
|
||||
}
|
||||
if (flags & MemBlockFlags::TEXTURE) {
|
||||
if (textureMap.FastFindWriteTag(MemBlockFlags::TEXTURE, start, size, tag))
|
||||
const char *tag = textureMap.FastFindWriteTag(MemBlockFlags::TEXTURE, start, size);
|
||||
if (tag)
|
||||
return tag;
|
||||
}
|
||||
return "";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::string GetMemWriteTagAt(uint32_t start, uint32_t size) {
|
||||
std::string tag = FindWriteTagByFlag(MemBlockFlags::WRITE, start, size);
|
||||
if (!tag.empty() && tag != "MemInit")
|
||||
return tag;
|
||||
|
||||
std::string GetMemWriteTagAt(const char *prefix, uint32_t start, uint32_t size) {
|
||||
const char *tag = FindWriteTagByFlag(MemBlockFlags::WRITE, start, size);
|
||||
if (tag && strcmp(tag, "MemInit") != 0)
|
||||
return std::string(prefix) + tag;
|
||||
// Fall back to alloc and texture, especially for VRAM. We prefer write above.
|
||||
tag = FindWriteTagByFlag(MemBlockFlags::ALLOC | MemBlockFlags::TEXTURE, start, size);
|
||||
if (!tag.empty())
|
||||
return tag;
|
||||
if (tag)
|
||||
return std::string(prefix) + tag;
|
||||
return StringFromFormat("%s%08x_size_%08x", prefix, start, size);
|
||||
}
|
||||
|
||||
return StringFromFormat("%08x_size_%08x", start, size);
|
||||
size_t FormatMemWriteTagAt(char *buf, size_t sz, const char *prefix, uint32_t start, uint32_t size) {
|
||||
const char *tag = FindWriteTagByFlag(MemBlockFlags::WRITE, start, size);
|
||||
if (tag && strcmp(tag, "MemInit") != 0) {
|
||||
return snprintf(buf, sz, "%s%s", prefix, tag);
|
||||
}
|
||||
// Fall back to alloc and texture, especially for VRAM. We prefer write above.
|
||||
tag = FindWriteTagByFlag(MemBlockFlags::ALLOC | MemBlockFlags::TEXTURE, start, size);
|
||||
if (tag) {
|
||||
return snprintf(buf, sz, "%s%s", prefix, tag);
|
||||
}
|
||||
return snprintf(buf, sz, "%s%08x_size_%08x", prefix, start, size);
|
||||
}
|
||||
|
||||
void MemBlockInfoInit() {
|
||||
|
||||
@@ -68,7 +68,9 @@ inline void NotifyMemInfo(MemBlockFlags flags, uint32_t start, uint32_t size, co
|
||||
std::vector<MemBlockInfo> FindMemInfo(uint32_t start, uint32_t size);
|
||||
std::vector<MemBlockInfo> FindMemInfoByFlag(MemBlockFlags flags, uint32_t start, uint32_t size);
|
||||
|
||||
std::string GetMemWriteTagAt(uint32_t start, uint32_t size);
|
||||
std::string GetMemWriteTagAt(const char *prefix, uint32_t start, uint32_t size);
|
||||
// Same as above but allocation-free.
|
||||
size_t FormatMemWriteTagAt(char *buf, size_t sz, const char *prefix, uint32_t start, uint32_t size);
|
||||
|
||||
void MemBlockInfoInit();
|
||||
void MemBlockInfoShutdown();
|
||||
|
||||
@@ -129,6 +129,6 @@ protected:
|
||||
|
||||
private:
|
||||
DialogStatus status = SCE_UTILITY_STATUS_NONE;
|
||||
UtilityDialogType dialogType_;
|
||||
UtilityDialogType dialogType_ = UtilityDialogType::NONE;
|
||||
bool volatileLocked_ = false;
|
||||
};
|
||||
@@ -285,9 +285,6 @@ struct SaveFileInfo
|
||||
|
||||
PPGeImage *texture = nullptr;
|
||||
|
||||
SaveFileInfo() {
|
||||
}
|
||||
|
||||
void DoState(PointerWrap &p);
|
||||
};
|
||||
|
||||
|
||||
@@ -159,7 +159,7 @@ static int Replace_memcpy() {
|
||||
RETURN(destPtr);
|
||||
|
||||
if (MemBlockInfoDetailed(bytes)) {
|
||||
const std::string tag = "ReplaceMemcpy/" + GetMemWriteTagAt(srcPtr, bytes);
|
||||
const std::string tag = GetMemWriteTagAt("ReplaceMemcpy/", srcPtr, bytes);
|
||||
NotifyMemInfo(MemBlockFlags::READ, srcPtr, bytes, tag.c_str(), tag.size());
|
||||
NotifyMemInfo(MemBlockFlags::WRITE, destPtr, bytes, tag.c_str(), tag.size());
|
||||
|
||||
@@ -211,7 +211,7 @@ static int Replace_memcpy_jak() {
|
||||
RETURN(destPtr);
|
||||
|
||||
if (MemBlockInfoDetailed(bytes)) {
|
||||
const std::string tag = "ReplaceMemcpy/" + GetMemWriteTagAt(srcPtr, bytes);
|
||||
const std::string tag = GetMemWriteTagAt("ReplaceMemcpy/", srcPtr, bytes);
|
||||
NotifyMemInfo(MemBlockFlags::READ, srcPtr, bytes, tag.c_str(), tag.size());
|
||||
NotifyMemInfo(MemBlockFlags::WRITE, destPtr, bytes, tag.c_str(), tag.size());
|
||||
|
||||
@@ -249,7 +249,7 @@ static int Replace_memcpy16() {
|
||||
RETURN(destPtr);
|
||||
|
||||
if (MemBlockInfoDetailed(bytes)) {
|
||||
const std::string tag = "ReplaceMemcpy16/" + GetMemWriteTagAt(srcPtr, bytes);
|
||||
const std::string tag = GetMemWriteTagAt("ReplaceMemcpy16/", srcPtr, bytes);
|
||||
NotifyMemInfo(MemBlockFlags::READ, srcPtr, bytes, tag.c_str(), tag.size());
|
||||
NotifyMemInfo(MemBlockFlags::WRITE, destPtr, bytes, tag.c_str(), tag.size());
|
||||
}
|
||||
@@ -290,7 +290,7 @@ static int Replace_memcpy_swizzled() {
|
||||
RETURN(0);
|
||||
|
||||
if (MemBlockInfoDetailed(pitch * h)) {
|
||||
const std::string tag = "ReplaceMemcpySwizzle/" + GetMemWriteTagAt(srcPtr, pitch * h);
|
||||
const std::string tag = GetMemWriteTagAt("ReplaceMemcpySwizzle/", srcPtr, pitch * h);
|
||||
NotifyMemInfo(MemBlockFlags::READ, srcPtr, pitch * h, tag.c_str(), tag.size());
|
||||
NotifyMemInfo(MemBlockFlags::WRITE, destPtr, pitch * h, tag.c_str(), tag.size());
|
||||
}
|
||||
@@ -321,7 +321,7 @@ static int Replace_memmove() {
|
||||
RETURN(destPtr);
|
||||
|
||||
if (MemBlockInfoDetailed(bytes)) {
|
||||
const std::string tag = "ReplaceMemmove/" + GetMemWriteTagAt(srcPtr, bytes);
|
||||
const std::string tag = GetMemWriteTagAt("ReplaceMemmove/", srcPtr, bytes);
|
||||
NotifyMemInfo(MemBlockFlags::READ, srcPtr, bytes, tag.c_str(), tag.size());
|
||||
NotifyMemInfo(MemBlockFlags::WRITE, destPtr, bytes, tag.c_str(), tag.size());
|
||||
}
|
||||
|
||||
+13
-11
@@ -64,8 +64,8 @@ int srcFrequency = 0;
|
||||
|
||||
const int hwSampleRate = 44100;
|
||||
|
||||
int hwBlockSize = 64;
|
||||
int hostAttemptBlockSize = 512;
|
||||
const int hwBlockSize = 64;
|
||||
const int hostAttemptBlockSize = 512;
|
||||
|
||||
static int audioIntervalCycles;
|
||||
static int audioHostIntervalCycles;
|
||||
@@ -82,6 +82,11 @@ static bool m_logAudio;
|
||||
static int chanQueueMaxSizeFactor;
|
||||
static int chanQueueMinSizeFactor;
|
||||
|
||||
// Accessor for libretro
|
||||
int __AudioGetHostAttemptBlockSize() {
|
||||
return hostAttemptBlockSize;
|
||||
}
|
||||
|
||||
static void hleAudioUpdate(u64 userdata, int cyclesLate) {
|
||||
// Schedule the next cycle first. __AudioUpdate() may consume cycles.
|
||||
CoreTiming::ScheduleEvent(audioIntervalCycles - cyclesLate, eventAudioUpdate, 0);
|
||||
@@ -110,8 +115,6 @@ void __AudioInit() {
|
||||
|
||||
chanQueueMaxSizeFactor = 2;
|
||||
chanQueueMinSizeFactor = 1;
|
||||
hwBlockSize = 64;
|
||||
hostAttemptBlockSize = 512;
|
||||
|
||||
__AudioCPUMHzChange();
|
||||
|
||||
@@ -338,7 +341,8 @@ void __AudioUpdate(bool resetRecording) {
|
||||
// to the CPU. Much better to throttle the frame rate on frame display and just throw away audio
|
||||
// if the buffer somehow gets full.
|
||||
bool firstChannel = true;
|
||||
std::vector<int16_t> srcBuffer;
|
||||
const int16_t srcBufferSize = hwBlockSize * 2;
|
||||
int16_t srcBuffer[srcBufferSize];
|
||||
|
||||
for (u32 i = 0; i < PSP_AUDIO_CHANNEL_MAX + 1; i++) {
|
||||
if (!chans[i].reserved)
|
||||
@@ -351,7 +355,7 @@ void __AudioUpdate(bool resetRecording) {
|
||||
}
|
||||
|
||||
bool needsResample = i == PSP_AUDIO_CHANNEL_SRC && srcFrequency != 0 && srcFrequency != mixFrequency;
|
||||
size_t sz = needsResample ? (hwBlockSize * 2 * srcFrequency) / mixFrequency : hwBlockSize * 2;
|
||||
size_t sz = needsResample ? (srcBufferSize * srcFrequency) / mixFrequency : srcBufferSize;
|
||||
if (sz > chanSampleQueues[i].size()) {
|
||||
ERROR_LOG(SCEAUDIO, "Channel %i buffer underrun at %i of %i", i, (int)chanSampleQueues[i].size() / 2, (int)sz / 2);
|
||||
}
|
||||
@@ -372,13 +376,11 @@ void __AudioUpdate(bool resetRecording) {
|
||||
return buf1[sz1 - 1];
|
||||
};
|
||||
|
||||
srcBuffer.resize(hwBlockSize * 2);
|
||||
|
||||
// TODO: This is terrible, since it's doing it by small chunk and discarding frac.
|
||||
const uint32_t ratio = (uint32_t)(65536.0 * srcFrequency / (double)mixFrequency);
|
||||
uint32_t frac = 0;
|
||||
size_t readIndex = 0;
|
||||
for (size_t outIndex = 0; readIndex < sz && outIndex < srcBuffer.size(); outIndex += 2) {
|
||||
for (size_t outIndex = 0; readIndex < sz && outIndex < srcBufferSize; outIndex += 2) {
|
||||
size_t readIndex2 = readIndex + 2;
|
||||
int16_t l1 = read(readIndex);
|
||||
int16_t r1 = read(readIndex + 1);
|
||||
@@ -393,8 +395,8 @@ void __AudioUpdate(bool resetRecording) {
|
||||
frac &= 0xffff;
|
||||
}
|
||||
|
||||
buf1 = srcBuffer.data();
|
||||
sz1 = srcBuffer.size();
|
||||
buf1 = srcBuffer;
|
||||
sz1 = srcBufferSize;
|
||||
buf2 = nullptr;
|
||||
sz2 = 0;
|
||||
}
|
||||
|
||||
@@ -50,6 +50,8 @@ int __AudioMix(short *outstereo, int numSamples, int sampleRate);
|
||||
void __AudioGetDebugStats(char *buf, size_t bufSize);
|
||||
void __PushExternalAudio(const s32 *audio, int numSamples); // Should not be used in-game, only at the menu!
|
||||
|
||||
int __AudioGetHostAttemptBlockSize();
|
||||
|
||||
// Audio Dumping stuff
|
||||
void __StartLogAudio(const Path &filename);
|
||||
void __StopLogAudio();
|
||||
|
||||
@@ -1268,7 +1268,7 @@ u32 _AtracDecodeData(int atracID, u8 *outbuf, u32 outbufPtr, u32 *SamplesNum, u3
|
||||
if (outbufPtr != 0) {
|
||||
u32 outBytes = numSamples * atrac->outputChannels_ * sizeof(s16);
|
||||
if (packetAddr != 0 && MemBlockInfoDetailed()) {
|
||||
const std::string tag = "AtracDecode/" + GetMemWriteTagAt(packetAddr, packetSize);
|
||||
const std::string tag = GetMemWriteTagAt("AtracDecode/", packetAddr, packetSize);
|
||||
NotifyMemInfo(MemBlockFlags::READ, packetAddr, packetSize, tag.c_str(), tag.size());
|
||||
NotifyMemInfo(MemBlockFlags::WRITE, outbufPtr, outBytes, tag.c_str(), tag.size());
|
||||
} else {
|
||||
|
||||
@@ -59,7 +59,7 @@ static int CommonDecompress(int windowBits, u32 OutBuffer, int OutBufferLength,
|
||||
}
|
||||
|
||||
if (MemBlockInfoDetailed(stream.total_in, stream.total_out)) {
|
||||
const std::string tag = "sceDeflt/" + GetMemWriteTagAt(InBuffer, stream.total_in);
|
||||
const std::string tag = GetMemWriteTagAt("sceDeflt/", InBuffer, stream.total_in);
|
||||
NotifyMemInfo(MemBlockFlags::READ, InBuffer, stream.total_in, tag.c_str(), tag.size());
|
||||
NotifyMemInfo(MemBlockFlags::WRITE, OutBuffer, stream.total_out, tag.c_str(), tag.size());
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ static int __DmacMemcpy(u32 dst, u32 src, u32 size) {
|
||||
if (!skip) {
|
||||
currentMIPS->InvalidateICache(src, size);
|
||||
if (MemBlockInfoDetailed(size)) {
|
||||
const std::string tag = "DmacMemcpy/" + GetMemWriteTagAt(src, size);
|
||||
const std::string tag = GetMemWriteTagAt("DmacMemcpy/", src, size);
|
||||
Memory::Memcpy(dst, src, size, tag.c_str(), tag.size());
|
||||
} else {
|
||||
Memory::Memcpy(dst, src, size, "DmacMemcpy");
|
||||
|
||||
@@ -656,7 +656,7 @@ static u32 sceKernelMemcpy(u32 dst, u32 src, u32 size)
|
||||
}
|
||||
|
||||
if (MemBlockInfoDetailed(size)) {
|
||||
const std::string tag = "KernelMemcpy/" + GetMemWriteTagAt(src, size);
|
||||
const std::string tag = GetMemWriteTagAt("KernelMemcpy/", src, size);
|
||||
NotifyMemInfo(MemBlockFlags::READ, src, size, tag.c_str(), tag.size());
|
||||
NotifyMemInfo(MemBlockFlags::WRITE, dst, size, tag.c_str(), tag.size());
|
||||
}
|
||||
@@ -691,7 +691,7 @@ static u32 sysclib_memcpy(u32 dst, u32 src, u32 size) {
|
||||
memcpy(Memory::GetPointerWriteUnchecked(dst), Memory::GetPointerUnchecked(src), size);
|
||||
}
|
||||
if (MemBlockInfoDetailed(size)) {
|
||||
const std::string tag = "KernelMemcpy/" + GetMemWriteTagAt(src, size);
|
||||
const std::string tag = GetMemWriteTagAt("KernelMemcpy/", src, size);
|
||||
NotifyMemInfo(MemBlockFlags::READ, src, size, tag.c_str(), tag.size());
|
||||
NotifyMemInfo(MemBlockFlags::WRITE, dst, size, tag.c_str(), tag.size());
|
||||
}
|
||||
@@ -794,7 +794,7 @@ static u32 sysclib_memmove(u32 dst, u32 src, u32 size) {
|
||||
memmove(Memory::GetPointerWriteUnchecked(dst), Memory::GetPointerUnchecked(src), size);
|
||||
}
|
||||
if (MemBlockInfoDetailed(size)) {
|
||||
const std::string tag = "KernelMemmove/" + GetMemWriteTagAt(src, size);
|
||||
const std::string tag = GetMemWriteTagAt("KernelMemmove/", src, size);
|
||||
NotifyMemInfo(MemBlockFlags::READ, src, size, tag.c_str(), tag.size());
|
||||
NotifyMemInfo(MemBlockFlags::WRITE, dst, size, tag.c_str(), tag.size());
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <cstring>
|
||||
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Common/StringUtils.h"
|
||||
#include "Core/Debugger/MemBlockInfo.h"
|
||||
#include "Core/MemMap.h"
|
||||
#include "Core/MIPS/MIPS.h"
|
||||
@@ -70,9 +71,9 @@ inline void Memcpy(const u32 to_address, const u32 from_address, const u32 len,
|
||||
if (MemBlockInfoDetailed(len)) {
|
||||
char tagData[128];
|
||||
if (!tag) {
|
||||
const std::string srcTag = GetMemWriteTagAt(from_address, len);
|
||||
const std::string srcTag = GetMemWriteTagAt("Memcpy/", from_address, len);
|
||||
tag = tagData;
|
||||
tagLen = snprintf(tagData, sizeof(tagData), "Memcpy/%s", srcTag.c_str());
|
||||
tagLen = truncate_cpy(tagData, srcTag.c_str());
|
||||
}
|
||||
NotifyMemInfo(MemBlockFlags::READ, from_address, len, tag, tagLen);
|
||||
NotifyMemInfo(MemBlockFlags::WRITE, to_address, len, tag, tagLen);
|
||||
|
||||
@@ -701,12 +701,11 @@ void DrawEngineCommon::SubmitPrim(const void *verts, const void *inds, GEPrimiti
|
||||
DeferredDrawCall &dc = drawCalls[numDrawCalls];
|
||||
dc.verts = verts;
|
||||
dc.inds = inds;
|
||||
dc.vertexCount = vertexCount;
|
||||
dc.indexType = (vertTypeID & GE_VTYPE_IDX_MASK) >> GE_VTYPE_IDX_SHIFT;
|
||||
dc.prim = prim;
|
||||
dc.vertexCount = vertexCount;
|
||||
dc.uvScale = gstate_c.uv;
|
||||
dc.cullMode = cullMode;
|
||||
|
||||
dc.uvScale = gstate_c.uv;
|
||||
if (inds) {
|
||||
GetIndexBounds(inds, vertexCount, vertTypeID, &dc.indexLowerBound, &dc.indexUpperBound);
|
||||
} else {
|
||||
|
||||
@@ -165,10 +165,10 @@ protected:
|
||||
u32 vertexCount;
|
||||
u8 indexType;
|
||||
s8 prim;
|
||||
u8 cullMode;
|
||||
u16 indexLowerBound;
|
||||
u16 indexUpperBound;
|
||||
UVScale uvScale;
|
||||
int cullMode;
|
||||
};
|
||||
|
||||
enum { MAX_DEFERRED_DRAW_CALLS = 128 };
|
||||
|
||||
@@ -905,7 +905,6 @@ void FramebufferManagerCommon::NotifyRenderFramebufferCreated(VirtualFramebuffer
|
||||
}
|
||||
|
||||
void FramebufferManagerCommon::NotifyRenderFramebufferUpdated(VirtualFramebuffer *vfb) {
|
||||
// ugly...
|
||||
if (gstate_c.curRTWidth != vfb->width || gstate_c.curRTHeight != vfb->height) {
|
||||
gstate_c.Dirty(DIRTY_PROJTHROUGHMATRIX | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_CULLRANGE);
|
||||
}
|
||||
@@ -922,6 +921,7 @@ void FramebufferManagerCommon::NotifyRenderFramebufferSwitched(VirtualFramebuffe
|
||||
} else {
|
||||
DownloadFramebufferOnSwitch(prevVfb);
|
||||
}
|
||||
|
||||
textureCache_->ForgetLastTexture();
|
||||
shaderManager_->DirtyLastShader();
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
#include "Common/Common.h"
|
||||
#include "Common/Data/Convert/ColorConv.h"
|
||||
#include "Common/Data/Collections/TinySet.h"
|
||||
#include "Common/Profiler/Profiler.h"
|
||||
#include "Common/MemoryUtil.h"
|
||||
#include "Common/StringUtils.h"
|
||||
@@ -616,18 +617,18 @@ TexCacheEntry *TextureCacheCommon::SetTexture() {
|
||||
bool TextureCacheCommon::GetBestFramebufferCandidate(const TextureDefinition &entry, u32 texAddrOffset, AttachCandidate *bestCandidate) const {
|
||||
gpuStats.numFramebufferEvaluations++;
|
||||
|
||||
std::vector<AttachCandidate> candidates;
|
||||
TinySet<AttachCandidate, 6> candidates;
|
||||
|
||||
const std::vector<VirtualFramebuffer *> &framebuffers = framebufferManager_->Framebuffers();
|
||||
|
||||
for (VirtualFramebuffer *framebuffer : framebuffers) {
|
||||
FramebufferMatchInfo match{};
|
||||
if (MatchFramebuffer(entry, framebuffer, texAddrOffset, RASTER_COLOR, &match)) {
|
||||
candidates.push_back(AttachCandidate{ match, entry, framebuffer, RASTER_COLOR, framebuffer->colorBindSeq });
|
||||
candidates.push_back(AttachCandidate{ framebuffer, match, RASTER_COLOR });
|
||||
}
|
||||
match = {};
|
||||
if (MatchFramebuffer(entry, framebuffer, texAddrOffset, RASTER_DEPTH, &match)) {
|
||||
candidates.push_back(AttachCandidate{ match, entry, framebuffer, RASTER_DEPTH, framebuffer->depthBindSeq });
|
||||
candidates.push_back(AttachCandidate{ framebuffer, match, RASTER_DEPTH });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -640,11 +641,11 @@ bool TextureCacheCommon::GetBestFramebufferCandidate(const TextureDefinition &en
|
||||
|
||||
if (Reporting::ShouldLogNTimes("multifbcandidate", 5)) {
|
||||
std::string cands;
|
||||
for (auto &candidate : candidates) {
|
||||
cands += candidate.ToString() + "\n";
|
||||
}
|
||||
for (size_t i = 0; i < candidates.size(); i++) {
|
||||
cands += candidates[i].ToString() + "\n";
|
||||
}
|
||||
|
||||
WARN_LOG_N_TIMES(multifbcandidate, 5, G3D, "GetFramebufferCandidates: Multiple (%d) candidate framebuffers. texaddr: %08x offset: %d (%dx%d stride %d, %s):\n%s",
|
||||
WARN_LOG(G3D, "GetFramebufferCandidates: Multiple (%d) candidate framebuffers. texaddr: %08x offset: %d (%dx%d stride %d, %s):\n%s",
|
||||
(int)candidates.size(),
|
||||
entry.addr, texAddrOffset, dimWidth(entry.dim), dimHeight(entry.dim), entry.bufw, GeTextureFormatToString(entry.format),
|
||||
cands.c_str()
|
||||
@@ -653,17 +654,17 @@ bool TextureCacheCommon::GetBestFramebufferCandidate(const TextureDefinition &en
|
||||
|
||||
// OK, multiple possible candidates. Will need to figure out which one is the most relevant.
|
||||
int bestRelevancy = -1;
|
||||
int bestIndex = -1;
|
||||
size_t bestIndex = -1;
|
||||
|
||||
bool kzCompat = PSP_CoreParameter().compat.flags().SplitFramebufferMargin;
|
||||
|
||||
// We simply use the sequence counter as relevancy nowadays.
|
||||
for (int i = 0; i < (int)candidates.size(); i++) {
|
||||
for (size_t i = 0; i < candidates.size(); i++) {
|
||||
const AttachCandidate &candidate = candidates[i];
|
||||
int relevancy = candidate.seqCount;
|
||||
int relevancy = candidate.channel == RASTER_COLOR ? candidate.fb->colorBindSeq : candidate.fb->depthBindSeq;
|
||||
|
||||
// Add a small negative penalty if the texture is currently bound as a framebuffer, and offset is not zero.
|
||||
// Should avoid problems when pingponging two nearby buffers, like in Wipeout Pure in #15927
|
||||
// Should avoid problems when pingponging two nearby buffers, like in Wipeout Pure in #15927.
|
||||
if (candidate.channel == RASTER_COLOR &&
|
||||
(candidate.match.yOffset != 0 || candidate.match.xOffset != 0) &&
|
||||
(candidate.fb->fb_address & 0x1FFFFF) == (gstate.getFrameBufAddress() & 0x1FFFFF)) {
|
||||
@@ -865,7 +866,7 @@ bool TextureCacheCommon::MatchFramebuffer(
|
||||
uint32_t fb_stride = channel == RASTER_DEPTH ? framebuffer->z_stride : framebuffer->fb_stride;
|
||||
GEBufferFormat fb_format = channel == RASTER_DEPTH ? GE_FORMAT_DEPTH16 : framebuffer->fb_format;
|
||||
|
||||
if (channel == RASTER_DEPTH && framebuffer->z_address == framebuffer->fb_address) {
|
||||
if (channel == RASTER_DEPTH && (framebuffer->z_address == framebuffer->fb_address || framebuffer->z_address == 0)) {
|
||||
// Try to avoid silly matches to somewhat malformed buffers.
|
||||
return false;
|
||||
}
|
||||
@@ -2248,7 +2249,7 @@ void TextureCacheCommon::ClearNextFrame() {
|
||||
std::string AttachCandidate::ToString() const {
|
||||
return StringFromFormat("[%s seq:%d C:%08x/%d(%s) Z:%08x/%d X:%d Y:%d reint: %s]",
|
||||
this->channel == RASTER_COLOR ? "COLOR" : "DEPTH",
|
||||
this->seqCount,
|
||||
this->channel == RASTER_COLOR ? this->fb->colorBindSeq : this->fb->depthBindSeq,
|
||||
this->fb->fb_address, this->fb->fb_stride, GeBufferFormatToString(this->fb->fb_format),
|
||||
this->fb->z_address, this->fb->z_stride,
|
||||
this->match.xOffset, this->match.yOffset, this->match.reinterpret ? "true" : "false");
|
||||
|
||||
@@ -93,12 +93,11 @@ class VulkanTexture;
|
||||
// Enough information about a texture to match it to framebuffers.
|
||||
struct TextureDefinition {
|
||||
u32 addr;
|
||||
u16 bufw;
|
||||
u16 dim;
|
||||
GETextureFormat format;
|
||||
u32 dim;
|
||||
u32 bufw;
|
||||
};
|
||||
|
||||
|
||||
// TODO: Shrink this struct. There is some fluff.
|
||||
|
||||
// NOTE: These only handle textures loaded directly from PSP memory contents.
|
||||
@@ -209,18 +208,16 @@ typedef std::map<u64, std::unique_ptr<TexCacheEntry>> TexCache;
|
||||
#endif
|
||||
|
||||
struct FramebufferMatchInfo {
|
||||
int xOffset;
|
||||
int yOffset;
|
||||
int16_t xOffset;
|
||||
int16_t yOffset;
|
||||
bool reinterpret;
|
||||
GEBufferFormat reinterpretTo;
|
||||
};
|
||||
|
||||
struct AttachCandidate {
|
||||
FramebufferMatchInfo match;
|
||||
TextureDefinition entry;
|
||||
VirtualFramebuffer *fb;
|
||||
FramebufferMatchInfo match;
|
||||
RasterChannel channel;
|
||||
int seqCount;
|
||||
|
||||
std::string ToString() const;
|
||||
};
|
||||
|
||||
@@ -176,9 +176,6 @@ void PrintDecodedVertex(VertexReader &vtx) {
|
||||
printf("P: %f %f %f\n", pos[0], pos[1], pos[2]);
|
||||
}
|
||||
|
||||
VertexDecoder::VertexDecoder() : decoded_(nullptr), ptr_(nullptr), jitted_(0), jittedSize_(0) {
|
||||
}
|
||||
|
||||
void VertexDecoder::Step_WeightsU8() const
|
||||
{
|
||||
u8 *wt = (u8 *)(decoded_ + decFmt.w0off);
|
||||
|
||||
@@ -125,10 +125,13 @@ public:
|
||||
case DEC_FLOAT_3:
|
||||
{
|
||||
const float *f = (const float *)(data_ + decFmt_.posoff);
|
||||
memcpy(pos, f, 12);
|
||||
if (isThrough()) {
|
||||
pos[0] = f[0];
|
||||
pos[1] = f[1];
|
||||
if (!isThrough()) {
|
||||
pos[2] = f[2];
|
||||
} else {
|
||||
// Integer value passed in a float. Clamped to 0, 65535.
|
||||
const float z = (int)pos[2] * (1.0f / 65535.0f);
|
||||
const float z = (int)f[2] * (1.0f / 65535.0f);
|
||||
pos[2] = z > 1.0f ? 1.0f : (z < 0.0f ? 0.0f : z);
|
||||
}
|
||||
}
|
||||
@@ -443,8 +446,6 @@ struct VertexDecoderOptions {
|
||||
|
||||
class VertexDecoder {
|
||||
public:
|
||||
VertexDecoder();
|
||||
|
||||
// A jit cache is not mandatory.
|
||||
void SetVertexType(u32 vtype, const VertexDecoderOptions &options, VertexDecoderJitCache *jitCache = nullptr);
|
||||
|
||||
@@ -549,11 +550,10 @@ public:
|
||||
int ToString(char *output) const;
|
||||
|
||||
// Mutable decoder state
|
||||
mutable u8 *decoded_;
|
||||
mutable const u8 *ptr_;
|
||||
|
||||
JittedVertexDecoder jitted_;
|
||||
int32_t jittedSize_;
|
||||
mutable u8 *decoded_ = nullptr;
|
||||
mutable const u8 *ptr_ = nullptr;
|
||||
JittedVertexDecoder jitted_ = 0;
|
||||
int32_t jittedSize_ = 0;
|
||||
|
||||
// "Immutable" state, set at startup
|
||||
|
||||
|
||||
+6
-5
@@ -2864,9 +2864,10 @@ void GPUCommon::DoBlockTransfer(u32 skipDrawReason) {
|
||||
if (MemBlockInfoDetailed(numBytes, numBytes)) {
|
||||
const uint32_t src = srcBasePtr + (srcY * srcStride + srcX) * bpp;
|
||||
const uint32_t dst = dstBasePtr + (dstY * dstStride + dstX) * bpp;
|
||||
const std::string tag = "GPUBlockTransfer/" + GetMemWriteTagAt(src, srcSize);
|
||||
NotifyMemInfo(MemBlockFlags::READ, src, srcSize, tag.c_str(), tag.size());
|
||||
NotifyMemInfo(MemBlockFlags::WRITE, dst, dstSize, tag.c_str(), tag.size());
|
||||
char tag[128];
|
||||
size_t tagSize = FormatMemWriteTagAt(tag, sizeof(tag), "GPUBlockTransfer/", src, srcSize);
|
||||
NotifyMemInfo(MemBlockFlags::READ, src, srcSize, tag, tagSize);
|
||||
NotifyMemInfo(MemBlockFlags::WRITE, dst, dstSize, tag, tagSize);
|
||||
}
|
||||
|
||||
// TODO: Correct timing appears to be 1.9, but erring a bit low since some of our other timing is inaccurate.
|
||||
@@ -2881,7 +2882,7 @@ bool GPUCommon::PerformMemoryCopy(u32 dest, u32 src, int size) {
|
||||
// Since they're identical we don't need to copy.
|
||||
if (!Memory::IsVRAMAddress(dest) || (dest ^ 0x00400000) != src) {
|
||||
if (MemBlockInfoDetailed(size)) {
|
||||
const std::string tag = "GPUMemcpy/" + GetMemWriteTagAt(src, size);
|
||||
const std::string tag = GetMemWriteTagAt("GPUMemcpy/", src, size);
|
||||
Memory::Memcpy(dest, src, size, tag.c_str(), tag.size());
|
||||
} else {
|
||||
Memory::Memcpy(dest, src, size, "GPUMemcpy");
|
||||
@@ -2893,7 +2894,7 @@ bool GPUCommon::PerformMemoryCopy(u32 dest, u32 src, int size) {
|
||||
}
|
||||
|
||||
if (MemBlockInfoDetailed(size)) {
|
||||
const std::string tag = "GPUMemcpy/" + GetMemWriteTagAt(src, size);
|
||||
const std::string tag = GetMemWriteTagAt("GPUMemcpy/", src, size);
|
||||
NotifyMemInfo(MemBlockFlags::READ, src, size, tag.c_str(), tag.size());
|
||||
NotifyMemInfo(MemBlockFlags::WRITE, dest, size, tag.c_str(), tag.size());
|
||||
}
|
||||
|
||||
@@ -813,7 +813,7 @@ void SoftGPU::Execute_BlockTransferStart(u32 op, u32 diff) {
|
||||
}
|
||||
|
||||
if (MemBlockInfoDetailed(srcSize, dstSize)) {
|
||||
const std::string tag = "GPUBlockTransfer/" + GetMemWriteTagAt(src, srcSize);
|
||||
const std::string tag = GetMemWriteTagAt("GPUBlockTransfer/", src, srcSize);
|
||||
NotifyMemInfo(MemBlockFlags::READ, src, srcSize, tag.c_str(), tag.size());
|
||||
NotifyMemInfo(MemBlockFlags::WRITE, dst, dstSize, tag.c_str(), tag.size());
|
||||
}
|
||||
|
||||
@@ -787,7 +787,7 @@ void DrawEngineVulkan::DoFlush() {
|
||||
lastRenderStepId_ = curRenderStepId;
|
||||
}
|
||||
|
||||
renderManager->BindPipeline(pipeline->pipeline, (PipelineFlags)pipeline->flags);
|
||||
renderManager->BindPipeline(pipeline->pipeline, (PipelineFlags)pipeline->flags, pipelineLayout_);
|
||||
if (pipeline != lastPipeline_) {
|
||||
if (lastPipeline_ && !(lastPipeline_->UsesBlendConstant() && pipeline->UsesBlendConstant())) {
|
||||
gstate_c.Dirty(DIRTY_BLEND_STATE);
|
||||
@@ -814,9 +814,9 @@ void DrawEngineVulkan::DoFlush() {
|
||||
if (!ibuf) {
|
||||
ibOffset = (uint32_t)frameData.pushIndex->Push(decIndex, sizeof(uint16_t) * indexGen.VertexCount(), &ibuf);
|
||||
}
|
||||
renderManager->DrawIndexed(pipelineLayout_, ds, ARRAY_SIZE(dynamicUBOOffsets), dynamicUBOOffsets, vbuf, vbOffset, ibuf, ibOffset, vertexCount, 1, VK_INDEX_TYPE_UINT16);
|
||||
renderManager->DrawIndexed(ds, ARRAY_SIZE(dynamicUBOOffsets), dynamicUBOOffsets, vbuf, vbOffset, ibuf, ibOffset, vertexCount, 1, VK_INDEX_TYPE_UINT16);
|
||||
} else {
|
||||
renderManager->Draw(pipelineLayout_, ds, ARRAY_SIZE(dynamicUBOOffsets), dynamicUBOOffsets, vbuf, vbOffset, vertexCount);
|
||||
renderManager->Draw(ds, ARRAY_SIZE(dynamicUBOOffsets), dynamicUBOOffsets, vbuf, vbOffset, vertexCount);
|
||||
}
|
||||
} else {
|
||||
PROFILE_THIS_SCOPE("soft");
|
||||
@@ -917,7 +917,7 @@ void DrawEngineVulkan::DoFlush() {
|
||||
lastRenderStepId_ = curRenderStepId;
|
||||
}
|
||||
|
||||
renderManager->BindPipeline(pipeline->pipeline, (PipelineFlags)pipeline->flags);
|
||||
renderManager->BindPipeline(pipeline->pipeline, (PipelineFlags)pipeline->flags, pipelineLayout_);
|
||||
if (pipeline != lastPipeline_) {
|
||||
if (lastPipeline_ && !lastPipeline_->UsesBlendConstant() && pipeline->UsesBlendConstant()) {
|
||||
gstate_c.Dirty(DIRTY_BLEND_STATE);
|
||||
@@ -949,11 +949,11 @@ void DrawEngineVulkan::DoFlush() {
|
||||
VkBuffer vbuf, ibuf;
|
||||
vbOffset = (uint32_t)frameData.pushVertex->Push(result.drawBuffer, maxIndex * sizeof(TransformedVertex), &vbuf);
|
||||
ibOffset = (uint32_t)frameData.pushIndex->Push(inds, sizeof(short) * result.drawNumTrans, &ibuf);
|
||||
renderManager->DrawIndexed(pipelineLayout_, ds, ARRAY_SIZE(dynamicUBOOffsets), dynamicUBOOffsets, vbuf, vbOffset, ibuf, ibOffset, result.drawNumTrans, 1, VK_INDEX_TYPE_UINT16);
|
||||
renderManager->DrawIndexed(ds, ARRAY_SIZE(dynamicUBOOffsets), dynamicUBOOffsets, vbuf, vbOffset, ibuf, ibOffset, result.drawNumTrans, 1, VK_INDEX_TYPE_UINT16);
|
||||
} else {
|
||||
VkBuffer vbuf;
|
||||
vbOffset = (uint32_t)frameData.pushVertex->Push(result.drawBuffer, result.drawNumTrans * sizeof(TransformedVertex), &vbuf);
|
||||
renderManager->Draw(pipelineLayout_, ds, ARRAY_SIZE(dynamicUBOOffsets), dynamicUBOOffsets, vbuf, vbOffset, result.drawNumTrans);
|
||||
renderManager->Draw(ds, ARRAY_SIZE(dynamicUBOOffsets), dynamicUBOOffsets, vbuf, vbOffset, result.drawNumTrans);
|
||||
}
|
||||
} else if (result.action == SW_CLEAR) {
|
||||
// Note: we won't get here if the clear is alpha but not color, or color but not alpha.
|
||||
|
||||
+1
-1
@@ -405,7 +405,7 @@ enum GELightComputation
|
||||
GE_LIGHTCOMP_ONLYPOWDIFFUSE = 2,
|
||||
};
|
||||
|
||||
enum GETextureFormat
|
||||
enum GETextureFormat : uint8_t
|
||||
{
|
||||
GE_TFMT_5650 = 0,
|
||||
GE_TFMT_5551 = 1,
|
||||
|
||||
@@ -379,7 +379,7 @@ class LibretroHost : public Host
|
||||
void InitSound() override {}
|
||||
void UpdateSound() override
|
||||
{
|
||||
extern int hostAttemptBlockSize;
|
||||
int hostAttemptBlockSize = __AudioGetHostAttemptBlockSize();
|
||||
const int blockSizeMax = 512;
|
||||
static int16_t audio[blockSizeMax * 2];
|
||||
assert(hostAttemptBlockSize <= blockSizeMax);
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
#include <jni.h>
|
||||
#endif
|
||||
|
||||
#include "Common/Data/Collections/TinySet.h"
|
||||
#include "Common/Data/Text/Parsers.h"
|
||||
#include "Common/Data/Text/WrapText.h"
|
||||
#include "Common/Data/Encoding/Utf8.h"
|
||||
@@ -308,6 +309,44 @@ bool TestParsers() {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TestTinySet() {
|
||||
TinySet<int, 4> a;
|
||||
EXPECT_EQ_INT((int)a.size(), 0);
|
||||
a.push_back(1);
|
||||
EXPECT_EQ_INT((int)a.size(), 1);
|
||||
a.push_back(2);
|
||||
EXPECT_EQ_INT((int)a.size(), 2);
|
||||
TinySet<int, 4> b;
|
||||
b.push_back(8);
|
||||
b.push_back(9);
|
||||
b.push_back(10);
|
||||
EXPECT_EQ_INT((int)b.size(), 3);
|
||||
|
||||
a.append(b);
|
||||
EXPECT_EQ_INT((int)a.size(), 5);
|
||||
EXPECT_EQ_INT((int)b.size(), 3);
|
||||
|
||||
b.append(b);
|
||||
EXPECT_EQ_INT((int)b.size(), 6);
|
||||
|
||||
EXPECT_EQ_INT(a[0], 1);
|
||||
EXPECT_EQ_INT(a[1], 2);
|
||||
EXPECT_EQ_INT(a[2], 8);
|
||||
EXPECT_EQ_INT(a[3], 9);
|
||||
EXPECT_EQ_INT(a[4], 10);
|
||||
a.append(a);
|
||||
EXPECT_EQ_INT(a.size(), 10);
|
||||
EXPECT_EQ_INT(a[9], 10);
|
||||
|
||||
b.push_back(11);
|
||||
EXPECT_EQ_INT((int)b.size(), 7);
|
||||
b.push_back(12);
|
||||
EXPECT_EQ_INT((int)b.size(), 8);
|
||||
b.push_back(13);
|
||||
EXPECT_EQ_INT(b.size(), 9);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TestVFPUSinCos() {
|
||||
float sine, cosine;
|
||||
InitVFPUSinCos();
|
||||
@@ -792,6 +831,7 @@ TestItem availableTests[] = {
|
||||
TEST_ITEM(AndroidContentURI),
|
||||
TEST_ITEM(ThreadManager),
|
||||
TEST_ITEM(WrapText),
|
||||
TEST_ITEM(TinySet),
|
||||
};
|
||||
|
||||
int main(int argc, const char *argv[]) {
|
||||
|
||||
Reference in new issue
Block a user