Я пытаюсь запустить симуляцию пульсации уже готового приложения. Сейчас процессор работает примерно на 11 мс на самых низких процессорах. Весь код в нем до сих пор работает на основном потоке.
Я надеюсь, что можно моделировать пульсацию целиком на другой поток.
Моделирование основано на проекте GLCameraRipple. В основном он создает тесселированный прямоугольник и вычисляет координаты текстуры. Таким образом, в идеальном мире координаты текстуры, а рябь, имитирующая массивы, все будет в другом потоке.
Функция обновления, с которой я сейчас работаю, выглядит следующим образом. Он использует сортировку GCD, но не получает от нее никакой скорости из-за синхронизации. Без синхронизации, однако, приложение потерпит крах, потому что быстрые массивы не являются потокобезопасными.
var rippleTexCoords:[GLfloat] = []
var rippleSource:[GLfloat] = []
var rippleDest:[GLfloat] = []
func runSimulation()
{
if (firstUpdate)
{firstUpdate = false; Whirl.crashLog("First update")}
let queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
let block1: (y: size_t) -> Void = {
(y: size_t) -> Void in
objc_sync_enter(self)
defer { objc_sync_exit(self) } // */ This will actually run at the end
let pw = self.poolWidthi
for x in 1..<(pw - 1)
{
let ai:Int = (y ) * (pw + 2) + x + 1
let bi:Int = (y + 2) * (pw + 2) + x + 1
let ci:Int = (y + 1) * (pw + 2) + x
let di:Int = (y + 1) * (pw + 2) + x + 2
let me:Int = (y + 1) * (pw + 2) + x + 1
let a = self.rippleSource[ai]
let b = self.rippleSource[bi]
let c = self.rippleSource[ci]
let d = self.rippleSource[di]
var result = self.rippleDest[me]
result = (a + b + c + d) / 2.0 - result
result -= result / 32.0
self.rippleDest[me] = result
}
//Defer goes here
}
dispatch_apply(Int(poolHeighti), queue, block1);
/*for y in 0..<poolHeighti {
block1(y: y)
}*/
let hm1 = GLfloat(poolHeight - 1)
let wm1 = GLfloat(poolWidth - 1)
let block2: (y: size_t) -> Void = {
(y: size_t) -> Void in
objc_sync_enter(self)
defer { objc_sync_exit(self) } // */
let yy = GLfloat(y)
let pw = self.poolWidthi
for x in 1..<(pw - 1) {
let xx = GLfloat(x)
let ai:Int = (y ) * (pw + 2) + x + 1
let bi:Int = (y + 2) * (pw + 2) + x + 1
let ci:Int = (y + 1) * (pw + 2) + x
let di:Int = (y + 1) * (pw + 2) + x + 2
let a = self.rippleDest[ai]
let b = self.rippleDest[bi]
let c = self.rippleDest[ci]
let d = self.rippleDest[di]
var s_offset = ((b - a) / 2048)
var t_offset = ((c - d) / 2048)
s_offset = (s_offset < -0.5) ? -0.5 : s_offset;
t_offset = (t_offset < -0.5) ? -0.5 : t_offset;
s_offset = (s_offset > 0.5) ? 0.5 : s_offset;
t_offset = (t_offset > 0.5) ? 0.5 : t_offset;
let s_tc = yy / hm1
let t_tc = xx / wm1
let me = (y * pw + x) * 2
self.rippleTexCoords[me + 0] = s_tc + s_offset
self.rippleTexCoords[me + 1] = t_tc + t_offset
}
}
dispatch_apply(poolHeighti, queue, block2)
/* for y in 0..<poolHeighti {
block2(y: y)
} *///
let pTmp = rippleDest
rippleDest = rippleSource
rippleSource = pTmp
}
Есть ли способ заставить этот код постоянно работать в другом потоке? Или как-нибудь заставить его идти быстрее?
Я не знаю, если бы это было возможно, но если бы это было, я бы имел эти массивы в следующем потоке:
Main:
- rippleVertices
- rippleIndices
Вторичный: (они никогда не читаются или не записываются в основной поток)
- rippleSource
- rippleDest
В обоих потоках:
- rippleTexCoords (читайте в основном потоке, написанном на вторичном потоке)
Если эти условия соблюдены, тогда метод runSimulation может быть запущен во втором потоке без проблем.