mirror of
https://github.com/hrydgard/ppsspp.git
synced 2024-11-27 23:40:39 +00:00
VK: Add extra safety checks around font texture creation. Motivated by some Play crashes.
This commit is contained in:
parent
a30da4b674
commit
f2244f789e
@ -56,10 +56,15 @@ public class TextRenderer {
|
||||
total.y = (int) (p.descent() - p.ascent()) * lines.length + 2;
|
||||
// Returning a 0 size can create problems when the caller
|
||||
// uses the measurement to create a texture.
|
||||
// Also, clamp to a reasonable maximum size.
|
||||
if (total.x < 1)
|
||||
total.x = 1;
|
||||
if (total.y < 1)
|
||||
total.y = 1;
|
||||
if (total.x > 2048)
|
||||
total.x = 2048;
|
||||
if (total.y > 2048)
|
||||
total.y = 2048;
|
||||
return total;
|
||||
}
|
||||
|
||||
|
@ -172,7 +172,8 @@ void TextDrawerAndroid::DrawString(DrawBuffer &target, const char *str, float x,
|
||||
if (iter != cache_.end()) {
|
||||
entry = iter->second.get();
|
||||
entry->lastUsedFrame = frameCount_;
|
||||
draw_->BindTexture(0, entry->texture);
|
||||
if (entry->texture)
|
||||
draw_->BindTexture(0, entry->texture);
|
||||
} else {
|
||||
double size = 0.0;
|
||||
auto iter = fontMap_.find(fontHash_);
|
||||
@ -195,8 +196,10 @@ void TextDrawerAndroid::DrawString(DrawBuffer &target, const char *str, float x,
|
||||
env_->DeleteLocalRef(jstr);
|
||||
|
||||
entry = new TextStringEntry();
|
||||
entry->bmWidth = entry->width = imageWidth;
|
||||
entry->bmHeight = entry->height = imageHeight;
|
||||
entry->bmWidth = imageWidth;
|
||||
entry->width = imageWidth;
|
||||
entry->bmHeight = imageHeight;
|
||||
entry->height = imageHeight;
|
||||
entry->lastUsedFrame = frameCount_;
|
||||
|
||||
TextureDesc desc{};
|
||||
@ -206,6 +209,7 @@ void TextDrawerAndroid::DrawString(DrawBuffer &target, const char *str, float x,
|
||||
desc.height = entry->bmHeight;
|
||||
desc.depth = 1;
|
||||
desc.mipLevels = 1;
|
||||
desc.generateMips = false;
|
||||
desc.tag = "TextDrawer";
|
||||
|
||||
uint16_t *bitmapData = new uint16_t[entry->bmWidth * entry->bmHeight];
|
||||
@ -224,13 +228,17 @@ void TextDrawerAndroid::DrawString(DrawBuffer &target, const char *str, float x,
|
||||
entry->texture = draw_->CreateTexture(desc);
|
||||
delete[] bitmapData;
|
||||
cache_[key] = std::unique_ptr<TextStringEntry>(entry);
|
||||
draw_->BindTexture(0, entry->texture);
|
||||
if (entry->texture) {
|
||||
draw_->BindTexture(0, entry->texture);
|
||||
}
|
||||
}
|
||||
float w = entry->bmWidth * fontScaleX_ * dpiScale_;
|
||||
float h = entry->bmHeight * fontScaleY_ * dpiScale_;
|
||||
DrawBuffer::DoAlign(align, &x, &y, &w, &h);
|
||||
target.DrawTexRect(x, y, x + w, y + h, 0.0f, 0.0f, 1.0f, 1.0f, color);
|
||||
target.Flush(true);
|
||||
if (entry->texture) {
|
||||
target.DrawTexRect(x, y, x + w, y + h, 0.0f, 0.0f, 1.0f, 1.0f, color);
|
||||
target.Flush(true);
|
||||
}
|
||||
}
|
||||
|
||||
void TextDrawerAndroid::ClearCache() {
|
||||
|
@ -380,7 +380,9 @@ VkCommandBuffer VulkanRenderManager::GetInitCmd() {
|
||||
VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT
|
||||
};
|
||||
VkResult res = vkBeginCommandBuffer(frameData.initCmd, &begin);
|
||||
_assert_(res == VK_SUCCESS);
|
||||
if (res != VK_SUCCESS) {
|
||||
return VK_NULL_HANDLE;
|
||||
}
|
||||
frameData.hasInitCommands = true;
|
||||
}
|
||||
return frameData_[curFrame].initCmd;
|
||||
|
@ -301,11 +301,9 @@ struct DescriptorSetKey {
|
||||
|
||||
class VKTexture : public Texture {
|
||||
public:
|
||||
VKTexture(VulkanContext *vulkan, VkCommandBuffer cmd, VulkanPushBuffer *pushBuffer, const TextureDesc &desc, VulkanDeviceAllocator *alloc)
|
||||
: vulkan_(vulkan), mipLevels_(desc.mipLevels), format_(desc.format) {
|
||||
bool result = Create(cmd, pushBuffer, desc, alloc);
|
||||
_assert_(result);
|
||||
}
|
||||
VKTexture(VulkanContext *vulkan, VkCommandBuffer cmd, VulkanPushBuffer *pushBuffer, const TextureDesc &desc)
|
||||
: vulkan_(vulkan), mipLevels_(desc.mipLevels), format_(desc.format) {}
|
||||
bool Create(VkCommandBuffer cmd, VulkanPushBuffer *pushBuffer, const TextureDesc &desc, VulkanDeviceAllocator *alloc);
|
||||
|
||||
~VKTexture() {
|
||||
Destroy();
|
||||
@ -322,8 +320,6 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
bool Create(VkCommandBuffer cmd, VulkanPushBuffer *pushBuffer, const TextureDesc &desc, VulkanDeviceAllocator *alloc);
|
||||
|
||||
void Destroy() {
|
||||
if (vkTex_) {
|
||||
vkTex_->Destroy();
|
||||
@ -335,9 +331,9 @@ private:
|
||||
VulkanContext *vulkan_;
|
||||
VulkanTexture *vkTex_ = nullptr;
|
||||
|
||||
int mipLevels_;
|
||||
int mipLevels_ = 0;
|
||||
|
||||
DataFormat format_;
|
||||
DataFormat format_ = DataFormat::UNDEFINED;
|
||||
};
|
||||
|
||||
class VKFramebuffer;
|
||||
@ -698,6 +694,10 @@ enum class TextureState {
|
||||
bool VKTexture::Create(VkCommandBuffer cmd, VulkanPushBuffer *push, const TextureDesc &desc, VulkanDeviceAllocator *alloc) {
|
||||
// Zero-sized textures not allowed.
|
||||
_assert_(desc.width * desc.height * desc.depth > 0); // remember to set depth to 1!
|
||||
if (desc.width * desc.height * desc.depth <= 0) {
|
||||
ELOG("Bad texture dimensions %dx%dx%d", desc.width, desc.height, desc.depth);
|
||||
return false;
|
||||
}
|
||||
_assert_(push);
|
||||
format_ = desc.format;
|
||||
mipLevels_ = desc.mipLevels;
|
||||
@ -1079,12 +1079,20 @@ InputLayout *VKContext::CreateInputLayout(const InputLayoutDesc &desc) {
|
||||
}
|
||||
|
||||
Texture *VKContext::CreateTexture(const TextureDesc &desc) {
|
||||
if (!push_ || !renderManager_.GetInitCmd()) {
|
||||
VkCommandBuffer initCmd = renderManager_.GetInitCmd();
|
||||
if (!push_ || !initCmd) {
|
||||
// Too early! Fail.
|
||||
ELOG("Can't create textures before the first frame has started.");
|
||||
return nullptr;
|
||||
}
|
||||
return new VKTexture(vulkan_, renderManager_.GetInitCmd(), push_, desc, allocator_);
|
||||
VKTexture *tex = new VKTexture(vulkan_, initCmd, push_, desc);
|
||||
if (tex->Create(initCmd, push_, desc, allocator_)) {
|
||||
return tex;
|
||||
} else {
|
||||
ELOG("Failed to create texture");
|
||||
delete tex;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void CopySide(VkStencilOpState &dest, const StencilSide &src) {
|
||||
|
Loading…
Reference in New Issue
Block a user