Войти
Unreal EngineФорумПрограммирование

Unreal Engine 4 многопоточность, семафоры

Страницы: 1 2 Следующая »
#0
14:03, 23 фев. 2015

Всем привет. Нужен семафор для разделения доступа к данным из разных потоков, я взял std::mutex и он падает на вызове lock(). Ковальски, варианты? )


#1
14:23, 23 фев. 2015

очевидно же что такой наглый вариант не покатит : )

эпики чётко отслеживают треды, откажись от всего с namespace std, ковыряй внутренности, например AsyncWork

#2
14:39, 23 фев. 2015
class ScopedLock
{
public:
  //
  ScopedLock(FCriticalSection& Mutex) : Mutex_(Mutex) { Mutex_.Lock(); }
  //
  ~ScopedLock() { Mutex_.Unlock(); }

private:
  //
  FCriticalSection& Mutex_;
};
#3
15:02, 23 фев. 2015

BingoBongo

Можно подумать, что нету в UE своих ?

#4
15:53, 23 фев. 2015

innuendo
конечно есть, и wmask знает, как они называются

#5
16:06, 23 фев. 2015

BingoBongo
Так тебе семафоры или просто мьютекс?!

#6
16:16, 23 фев. 2015

Есть еще такое.

FThreadSafeCounter StopWorkerCounter;

uint32 TaskManager::Run()
{
  while (!StopWorkerCounter.GetValue())
  {
    ...
  }
}

TaskManager::~TaskManager()
{
  StopWorkerCounter.Increment();
  Thread->WaitForCompletion();
  ...
}
#7
19:03, 23 фев. 2015

что я делаю не так? давайте дебажить код:

есть структура с полем FCriticalSection

  enum E_SECTOR_STATE
  {
    ESS_NAKED,
    ESS_VISIBLED,
    ESS_NON_VISIBLED,
  };

  struct FSector
  {
    FVector normal;
    uint32 firstIndex;

    E_SECTOR_STATE state;
    FCriticalSection critical;
    UMaterialInstanceDynamic *material;
    UTexture2D* texture;
  };

есть массив. к его элементам обращаются с разных потоков.

  TArray<FSector> sectors;

есть метод update, который вызывается в одном потоке

void UPlanetMeshComponent::update()
{
  FSector* pSector;

  FVector cameraPosite;
  FRotator cameraRotate;
  GetWorld()->GetFirstPlayerController()->GetPlayerViewPoint(cameraPosite,cameraRotate);

  FVector planetPosite=GetComponentTransform().GetLocation();
  FQuat planetRotate=GetComponentTransform().GetRotation();

  FVector normal=(cameraPosite-planetPosite).UnsafeNormal();
  normal=planetRotate.Inverse().RotateVector(normal);

  for(int i=0;i<earthHeight*2;i++)
  {
    for (int j = 0; j<earthHeight; j++)
    {
      pSector=getSector(i,j);

      bool visibled = (normal | pSector->normal)>0.95f;
      
      pSector->critical.Lock();

      if (pSector->state!=ESS_VISIBLED && visibled)   //!!! Падает тут
      {
        FString name = FString(TEXT("tx_")) + FString::FromInt(i) + FString(TEXT("_")) + FString::FromInt(j);
        FString path = FString(TEXT("/Game/earth/")) +name+FString(TEXT("."))+name;
        pSector->texture=Cast<UTexture2D>(StaticLoadObject(UTexture2D::StaticClass(), NULL, &path.GetCharArray()[0]));
        pSector->material = UMaterialInstanceDynamic::Create(pMaterial, this);
        pSector->material->SetTextureParameterValue(TEXT("param_texture"), pSector->texture);

        pSector->state = ESS_VISIBLED;
      }
      else if (pSector->state != ESS_NON_VISIBLED && !visibled)
      {
        if (pSector->material->IsValidLowLevel())
        {
          pSector->material->ConditionalBeginDestroy();
          pSector->material=NULL;
        }
        if (pSector->texture->IsValidLowLevel())
        {
          pSector->texture->ConditionalBeginDestroy();
          pSector->texture=NULL;
        }

        pSector->state = ESS_NON_VISIBLED;
      }

      pSector->critical.Unlock();
    }
  }

//  GetWorld()->ForceGarbageCollection(true);
}

есть метод DrawBlaBlaBla, который вызывается в другом потоке

void UPlanetMeshComponent::FPlanetMeshSceneProxy::DrawDynamicElements(FPrimitiveDrawInterface* PDI, const FSceneView* View)
{
  QUICK_SCOPE_CYCLE_COUNTER(STAT_GeneratedMeshSceneProxy_DrawDynamicElements);

  const bool bWireframe = View->Family->EngineShowFlags.Wireframe;

  auto WireframeMaterialInstance = new FColoredMaterialRenderProxy(
    GEngine->WireframeMaterial ? GEngine->WireframeMaterial->GetRenderProxy(IsSelected()) : NULL,
    FLinearColor(0, 0.5f, 1.f)
    );

  FSector* pSector;

  for (int i = 0; i<pPlanetMeshComponent->sectors.Num();i++)
  {
    pSector = &pPlanetMeshComponent->sectors[i];

    pSector->critical.Lock();

    if (pSector->state == ESS_VISIBLED || pSector->state == ESS_NAKED)
    {
      FMeshBatch Mesh;
      FMeshBatchElement& BatchElement = Mesh.Elements[0];
      BatchElement.IndexBuffer = &IndexBuffer;
      Mesh.bWireframe = bWireframe;
      Mesh.VertexFactory = &VertexFactory;

      if (bWireframe)
        Mesh.MaterialRenderProxy = WireframeMaterialInstance;
      else if (pSector->state == ESS_VISIBLED)
        Mesh.MaterialRenderProxy = pSector->material->GetRenderProxy(IsSelected());
      else
        Mesh.MaterialRenderProxy = UMaterial::GetDefaultMaterial(MD_Surface)->GetRenderProxy(IsSelected());

      BatchElement.PrimitiveUniformBuffer = CreatePrimitiveUniformBufferImmediate(GetLocalToWorld(), GetBounds(), GetLocalBounds(), true, UseEditorDepthTest());
      BatchElement.FirstIndex = pSector->firstIndex;
      BatchElement.NumPrimitives = 2;
      BatchElement.MinVertexIndex = 0;
      BatchElement.MaxVertexIndex = VertexBuffer.Vertices.Num() - 1;
      Mesh.ReverseCulling = IsLocalToWorldDeterminantNegative();
      Mesh.Type = PT_TriangleList;
      Mesh.DepthPriorityGroup = SDPG_World;
      PDI->DrawMesh(Mesh);
    }

    pSector->critical.Unlock();
  }
}

Когда я вместо FCriticalSection использовал bool, чтобы разделить потоки, то все работало, но однажды падало. когда я решил сделать по-умному и использовать FCriticalSection, то падать стало практически сразу. Где падает я отметил комментарием (!!!). Почему не работает то? Я чувствую, что за разгадку могут дать нобелевскую премию ))

#8
19:07, 23 фев. 2015

Я бы сказал что в твой sectors кто то добавляет элементы. И тем самым грохает твой указатель на pSector

#9
19:25, 23 фев. 2015

Стас
не, sectors инициализируется в конструкторе и больше не меняется. в одном потоке его элементы отрисовываются, в другом слегка обновляются (для видимых грузятся материалы, для невидимых удаляются). и опять же без FCriticalSection как-то работало секунд 40-50 без перебоев.

#10
19:52, 23 фев. 2015

сделал создание всех FCriticalSection динамическим через new, и все разрулилось. нобелевка моя.

#11
21:26, 23 фев. 2015

охренеть костыль. Тебя не смущает, что поток рендеринга не просто так сделан параллельно (и более того - остается от "мира" на 2-3 кадра), а для доступа к нему - юзаются свои трики?

#12
22:07, 23 фев. 2015

BingoBongo
> UMaterialInstanceDynamic::Create

Всё должно нормально работать, пока ты вот это чудо не вызываешь ... см примеры в движке

#13
23:07, 23 фев. 2015

ufna
иии?

innuendo
это не чудо, а рекомендации по реализации с их форума. твои предложения?

#14
23:42, 23 фев. 2015

ufna
> (и более того - остается от "мира" на 2-3 кадра)
пруф?

Страницы: 1 2 Следующая »
Unreal EngineФорумПрограммирование

Тема в архиве.