Jump to content

Texture clears on Engine::swap


photo

Recommended Posts

Работаю над собственным рендерингом UI. У меня есть вектор структур, которые содержат вершины, индексы и TexturePtr. И рендерю я всё это, как в примере ImGui (как в ImGuiImpl::draw_callback) - та же идея задавать RenderState, залить всё в меш, затем внутри render_target->enable/disable в цикле задавать текстуру для материала и рендерить меш с оффсетом по вершинам и индексам, а затем идёт точно такой же код, как и в примере, ни капельки не изменнёный. Я понимаю, что этого может быть мало, поэтому если надо, могу подробнее показать.
У меня после одного такого прохода функции перестают работать текстуры. Поэтому я снарядился дебаггером и выяснил, что с умным указателем всё в порядке - рефкаунт в порядке, с указателем внутри тоже действий не было, под ним осталась Texture/APIInterface. А вот с объектом внутри APIInterface, в моём случае, с D3D11Texture произошло нехорошее - оно удалилось и стало NULL. Дальше дебаггером я выяснил, что при вызове Engine::swap(), данная текстура/данный объект очищается и вызывается деструктор. Когда я начал отслеживать текстуру внутри ImGui, то там такой подставы не произошло. В чём причина и как это пофиксить?

Link to comment

snaulx

Без какого-то внятного кода для воспроизведения сложно сказать. Если есть возможность, можете подготовить сэмпл, чтобы можно было запуститься локально и отладиться?

Спасибо.

How to submit a good bug report
---
FTP server for test scenes and user uploads:

Link to comment

Будет очень тяжело такое сделать, так как в проекте много зависимостей и т.д. + У нас закрытый исходный код, поэтому если кода надо скинуть много, то я скину его вам в лс.

Link to comment

Здравствуйте!

скачал и запустил ваш проект. 
запустил мир dev/ui/ui_test_world
в консоли много ошибок
```
Passed geometry doesn't contain valid texture. Remove it from pool.
``` 
нашел где выводится данная ошибка

RmlRenderInterface.cpp:229

if (!g.texture) {
    Log::error("Passed geometry doesn't contain valid texture. Remove it from pool.\n");
    continue;
}


отлично. начал искать где и кто ее создает, иии не нашел. никто никогда не назначал в Geometry::texture никакого значения.

если в вашем сообщении вы говорили про эту текстуру, то она не удаляется - она никогда не создавалась.

Link to comment

868961396_.png.92e7ba4e49758288d4481bc2f13b38c4.png
Ошибку я поставил, чтобы не крашилось из-за как раз этого бага. И текстура есть как раз таки в первом кадре, по дебагу я это отследил. Потом происходит то, что я описывал в первом сообщении. В геометрию текстура задаётся в CompileGeometry на 42 строке.

Link to comment

окей, теперь вижу откуда пришла текстура

в LoadTexture и GenerateTexture вы загружаете Unigine текстуры. но наружу отдаете Rml::TextureHandle который не хранит счетчик ссылок. 
тем самым при выходе из скоупа счетчик ссылок = 0. однако объект не умирает сразу - потому что Texture это ссылка на GPU ресурс, который будет удален в свапе. 

поэтому все верно, когда вы обращаетесь в этом же кадре, объект еще присутствует, а в следующем уже мертв. 

 

это можно решить путем добавления всех созданных текстур в контейнер в котором они будут всегда хранится, чтобы не потерять на них ссылку

public:
	bool LoadTexture(Rml::TextureHandle &texture_handle,
		Rml::Vector2i &texture_dimensions,
		const Rml::String &source) override
	{
		// do some
		TexturePtr texture = Texture::create(); // после создания текстуры
		all_generated_textures.append(texture); // добавляем ее в контейнер
		//
	}
	bool GenerateTexture(Rml::TextureHandle &texture_handle,
		const Rml::byte *source,
		const Rml::Vector2i &source_dimensions) override;
	{
		// do some
		TexturePtr texture = Texture::create(); // создаем текстуру
		all_generated_textures.append(texture); // добавляем в контейнер
		//
	}
	void ReleaseTexture(Rml::TextureHandle texture_handle) override;
	{
		// do some
		TexturePtr texture = // ...
		all_generated_textures.removeOne(texture); // для удаления текстуры, сначала выкидываем из контенера
		texture.deleteLater(); // потом просим движок удалить текстуру когда она будет не нужна. force не надо
		//
	}

private:
	Vector<Unigine::TexturePtr> all_generated_textures; // контейнер. 

возможно лучше даже использовать не vector а какой нибудь hashmap <rml::textureHandle, Unigine::TexturePtr> (ток придется какойто хешер писать) 
чтобы избежать разыменования птр и обратно конструирования птр на сырых указателях 
но нужно проверять, возможно никакой разницы по перфу не будет. 

 

 

Link to comment

Правда появилась другая проблема, не связанная с этой (хотя кто знает). У меня не рендерится ничего. Функция вызывается, в рендердоке отображаются DrawIndexed, меши и текстуры, но на финальном результате ничего не видно. Я как-то неправильно вызываю рендер или просто ошибка в ассетах?
Если что в том коде, я помимо пула текстур ещё пофиксил оффсеты для вершин и индексов.

изображение.png

изображение.png

изображение.png

Link to comment

Здравствуйте! 

вы подписались не на тот евент

у вас RmlRenderInterface.cpp:12

Engine::get()->getEventEndPluginsGui().connect(this, &RmlRenderInterface::draw);
// а надо 
Render::getEventEndScreen().connect(this, &RmlRenderInterface::draw);

в итоге чтото начинает рендится 
image.png

 

связано с тем, что Render::getTemporaryRenderTarget() и Renderer::getTextureColor() только во время рендера указывают на таргет текущего рендера и на текущую текстуру. в остальных случаях это Temprorary ресурсы, результат изменения которых никуда не идет

Link to comment
×
×
  • Create New...