blur perf warning
This commit is contained in:
@@ -1,6 +1,9 @@
|
|||||||
-- Lua 5.2+ compatibility for unpack
|
-- Lua 5.2+ compatibility for unpack
|
||||||
local unpack = table.unpack or unpack
|
local unpack = table.unpack or unpack
|
||||||
|
|
||||||
|
-- Warning cache to prevent duplicate warnings for the same element
|
||||||
|
local warningCache = {}
|
||||||
|
|
||||||
local Cache = {
|
local Cache = {
|
||||||
canvases = {},
|
canvases = {},
|
||||||
quads = {},
|
quads = {},
|
||||||
@@ -10,6 +13,7 @@ local Cache = {
|
|||||||
MAX_QUAD_SIZE = 20,
|
MAX_QUAD_SIZE = 20,
|
||||||
MAX_BLURRED_CANVAS_CACHE = 50, -- Maximum cached blurred canvases
|
MAX_BLURRED_CANVAS_CACHE = 50, -- Maximum cached blurred canvases
|
||||||
INTENSITY_THRESHOLD = 5, -- Skip blur below this intensity
|
INTENSITY_THRESHOLD = 5, -- Skip blur below this intensity
|
||||||
|
LARGE_BLUR_THRESHOLD = 250 * 250, -- Warn if blur area exceeds this (250x250px)
|
||||||
}
|
}
|
||||||
|
|
||||||
--- Round canvas size to nearest bucket for better reuse
|
--- Round canvas size to nearest bucket for better reuse
|
||||||
@@ -158,7 +162,7 @@ function Cache.setBlurredCanvas(key, canvas)
|
|||||||
for _ in pairs(Cache.blurredCanvases) do
|
for _ in pairs(Cache.blurredCanvases) do
|
||||||
count = count + 1
|
count = count + 1
|
||||||
end
|
end
|
||||||
|
|
||||||
if count >= Cache.MAX_BLURRED_CANVAS_CACHE then
|
if count >= Cache.MAX_BLURRED_CANVAS_CACHE then
|
||||||
-- Remove oldest entry
|
-- Remove oldest entry
|
||||||
local oldestKey = nil
|
local oldestKey = nil
|
||||||
@@ -169,7 +173,7 @@ function Cache.setBlurredCanvas(key, canvas)
|
|||||||
oldestKey = k
|
oldestKey = k
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if oldestKey then
|
if oldestKey then
|
||||||
if Cache.blurredCanvases[oldestKey].canvas then
|
if Cache.blurredCanvases[oldestKey].canvas then
|
||||||
Cache.blurredCanvases[oldestKey].canvas:release()
|
Cache.blurredCanvases[oldestKey].canvas:release()
|
||||||
@@ -177,7 +181,7 @@ function Cache.setBlurredCanvas(key, canvas)
|
|||||||
Cache.blurredCanvases[oldestKey] = nil
|
Cache.blurredCanvases[oldestKey] = nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
Cache.blurredCanvases[key] = {
|
Cache.blurredCanvases[key] = {
|
||||||
canvas = canvas,
|
canvas = canvas,
|
||||||
lastUsed = os.time(),
|
lastUsed = os.time(),
|
||||||
@@ -205,11 +209,12 @@ function Cache.clear()
|
|||||||
entry.canvas:release()
|
entry.canvas:release()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
Cache.canvases = {}
|
Cache.canvases = {}
|
||||||
Cache.quads = {}
|
Cache.quads = {}
|
||||||
Cache.blurInstances = {}
|
Cache.blurInstances = {}
|
||||||
Cache.blurredCanvases = {}
|
Cache.blurredCanvases = {}
|
||||||
|
warningCache = {} -- Clear warning cache on cache clear
|
||||||
end
|
end
|
||||||
|
|
||||||
-- ============================================================================
|
-- ============================================================================
|
||||||
@@ -287,14 +292,14 @@ function Cache.getBlurInstance(quality)
|
|||||||
if taps % 2 == 0 then
|
if taps % 2 == 0 then
|
||||||
taps = taps + 1
|
taps = taps + 1
|
||||||
end
|
end
|
||||||
|
|
||||||
local shader = ShaderBuilder.build(taps, 1.0, "weighted", -1)
|
local shader = ShaderBuilder.build(taps, 1.0, "weighted", -1)
|
||||||
Cache.blurInstances[quality] = {
|
Cache.blurInstances[quality] = {
|
||||||
shader = shader,
|
shader = shader,
|
||||||
taps = taps,
|
taps = taps,
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
return Cache.blurInstances[quality]
|
return Cache.blurInstances[quality]
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -309,6 +314,50 @@ end
|
|||||||
local Blur = {}
|
local Blur = {}
|
||||||
Blur.__index = Blur
|
Blur.__index = Blur
|
||||||
|
|
||||||
|
--- Check if we should warn about large blur area in immediate mode
|
||||||
|
---@param elementId string|nil Element ID for caching warnings
|
||||||
|
---@param width number Blur area width
|
||||||
|
---@param height number Blur area height
|
||||||
|
---@param blurType string "content" or "backdrop"
|
||||||
|
local function checkLargeBlurWarning(elementId, width, height, blurType)
|
||||||
|
-- Skip if no ErrorHandler available
|
||||||
|
if not Blur._ErrorHandler then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Skip if not in immediate mode
|
||||||
|
if not Blur._immediateModeOptimizations then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Calculate blur area
|
||||||
|
local area = width * height
|
||||||
|
|
||||||
|
-- Skip if area is below threshold
|
||||||
|
if area <= Cache.LARGE_BLUR_THRESHOLD then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Generate warning key (use elementId if available, otherwise use dimensions)
|
||||||
|
local warningKey = elementId or string.format("%dx%d:%s", width, height, blurType)
|
||||||
|
|
||||||
|
-- Skip if already warned for this element/area
|
||||||
|
if warningCache[warningKey] then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Mark as warned
|
||||||
|
warningCache[warningKey] = true
|
||||||
|
|
||||||
|
-- Issue warning
|
||||||
|
local message = string.format("Large %s blur area detected (%dx%d = %d pixels) in immediate mode", blurType, width, height, area)
|
||||||
|
|
||||||
|
local suggestion =
|
||||||
|
"Consider using retained mode for this component to avoid recreating blur effects every frame. Large blur operations are expensive and can cause performance issues in immediate mode."
|
||||||
|
|
||||||
|
Blur._ErrorHandler:warn("Blur", "PERF_003", message, suggestion)
|
||||||
|
end
|
||||||
|
|
||||||
--- Create a new blur effect instance
|
--- Create a new blur effect instance
|
||||||
---@param props BlurProps? Blur configuration
|
---@param props BlurProps? Blur configuration
|
||||||
---@return Blur blur The new blur instance
|
---@return Blur blur The new blur instance
|
||||||
@@ -355,6 +404,9 @@ function Blur:applyToRegion(intensity, x, y, width, height, drawFunc)
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Check for large blur area in immediate mode
|
||||||
|
checkLargeBlurWarning(nil, width, height, "content")
|
||||||
|
|
||||||
intensity = math.max(0, math.min(100, intensity))
|
intensity = math.max(0, math.min(100, intensity))
|
||||||
|
|
||||||
-- Intensity 0-100 maps to 0-5 passes
|
-- Intensity 0-100 maps to 0-5 passes
|
||||||
@@ -508,10 +560,10 @@ function Blur:applyBackdropCached(intensity, x, y, width, height, backdropCanvas
|
|||||||
if not Blur._immediateModeOptimizations or not elementId then
|
if not Blur._immediateModeOptimizations or not elementId then
|
||||||
return self:applyBackdrop(intensity, x, y, width, height, backdropCanvas)
|
return self:applyBackdrop(intensity, x, y, width, height, backdropCanvas)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Generate cache key
|
-- Generate cache key
|
||||||
local cacheKey = Cache.generateBlurCacheKey(elementId, x, y, width, height, intensity, self.quality, true)
|
local cacheKey = Cache.generateBlurCacheKey(elementId, x, y, width, height, intensity, self.quality, true)
|
||||||
|
|
||||||
-- Check cache
|
-- Check cache
|
||||||
local cachedCanvas = Cache.getBlurredCanvas(cacheKey)
|
local cachedCanvas = Cache.getBlurredCanvas(cacheKey)
|
||||||
if cachedCanvas then
|
if cachedCanvas then
|
||||||
@@ -520,17 +572,17 @@ function Blur:applyBackdropCached(intensity, x, y, width, height, backdropCanvas
|
|||||||
local prevShader = love.graphics.getShader()
|
local prevShader = love.graphics.getShader()
|
||||||
local prevColor = { love.graphics.getColor() }
|
local prevColor = { love.graphics.getColor() }
|
||||||
local prevBlendMode = love.graphics.getBlendMode()
|
local prevBlendMode = love.graphics.getBlendMode()
|
||||||
|
|
||||||
love.graphics.setCanvas(prevCanvas)
|
love.graphics.setCanvas(prevCanvas)
|
||||||
love.graphics.setShader()
|
love.graphics.setShader()
|
||||||
love.graphics.setBlendMode(prevBlendMode)
|
love.graphics.setBlendMode(prevBlendMode)
|
||||||
love.graphics.draw(cachedCanvas, x, y)
|
love.graphics.draw(cachedCanvas, x, y)
|
||||||
|
|
||||||
love.graphics.setShader(prevShader)
|
love.graphics.setShader(prevShader)
|
||||||
love.graphics.setColor(unpack(prevColor))
|
love.graphics.setColor(unpack(prevColor))
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Not cached, render and cache
|
-- Not cached, render and cache
|
||||||
if not backdropCanvas then
|
if not backdropCanvas then
|
||||||
if Blur._ErrorHandler then
|
if Blur._ErrorHandler then
|
||||||
@@ -548,6 +600,9 @@ function Blur:applyBackdropCached(intensity, x, y, width, height, backdropCanvas
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Check for large blur area in immediate mode
|
||||||
|
checkLargeBlurWarning(elementId, width, height, "backdrop")
|
||||||
|
|
||||||
intensity = math.max(0, math.min(100, intensity))
|
intensity = math.max(0, math.min(100, intensity))
|
||||||
|
|
||||||
local passes = math.ceil(intensity / 20)
|
local passes = math.ceil(intensity / 20)
|
||||||
|
|||||||
@@ -291,6 +291,12 @@ local ErrorCodes = {
|
|||||||
description = "Critical performance threshold exceeded",
|
description = "Critical performance threshold exceeded",
|
||||||
suggestion = "Operation is causing frame drops. Consider optimizing or reducing frequency.",
|
suggestion = "Operation is causing frame drops. Consider optimizing or reducing frequency.",
|
||||||
},
|
},
|
||||||
|
PERF_003 = {
|
||||||
|
code = "FLEXLOVE_PERF_003",
|
||||||
|
category = "PERF",
|
||||||
|
description = "Large blur area in immediate mode",
|
||||||
|
suggestion = "Consider using retained mode for this component to avoid recreating blur effects every frame.",
|
||||||
|
},
|
||||||
|
|
||||||
-- Memory Warnings (MEM_001 - MEM_099)
|
-- Memory Warnings (MEM_001 - MEM_099)
|
||||||
MEM_001 = {
|
MEM_001 = {
|
||||||
|
|||||||
Reference in New Issue
Block a user