// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved. #pragma once #include "Engine/Platform/Platform.h" #include "Engine/Core/Collections/Array.h" /// /// Tracking of per-resource or per-subresource state for GPU resources that require to issue resource access barriers during rendering. /// template class GPUResourceState { private: /// /// The whole resource state (used only if _allSubresourcesSame is 1). /// StateType _resourceState : 31; /// /// Set to 1 if _resourceState is valid. In this case, all subresources have the same state. /// Set to 0 if _subresourceState is valid. In this case, each subresources may have a different state (or may be unknown). /// uint32 _allSubresourcesSame : 1; /// /// The per subresource state (used only if _allSubresourcesSame is 0). /// Array _subresourceState; public: /// /// Initializes a new instance of the class. /// GPUResourceState() : _resourceState(InvalidState) , _allSubresourcesSame(true) { } public: void Initialize(uint32 subresourceCount, StateType initialState, bool usePerSubresourceTracking) { ASSERT(_subresourceState.IsEmpty() && subresourceCount > 0); _allSubresourcesSame = true; _resourceState = initialState; if (usePerSubresourceTracking && subresourceCount > 1) _subresourceState.Resize(subresourceCount, false); #if BUILD_DEBUG _subresourceState.SetAll(InvalidState); #endif } bool IsInitializated() const { return _resourceState != InvalidState || _subresourceState.HasItems(); } void Release() { _resourceState = InvalidState; _subresourceState.Resize(0); } bool AreAllSubresourcesSame() const { return _allSubresourcesSame; } int32 GetSubresourcesCount() const { return _subresourceState.Count(); } bool CheckResourceState(StateType state) const { if (_allSubresourcesSame) return state == _resourceState; for (int32 i = 0; i < _subresourceState.Count(); i++) { if (_subresourceState[i] != state) return false; } return true; } StateType GetSubresourceState(uint32 subresourceIndex) const { if (_allSubresourcesSame) return _resourceState; ASSERT(subresourceIndex >= 0 && subresourceIndex < static_cast(_subresourceState.Count())); return _subresourceState[subresourceIndex]; } void SetResourceState(StateType state) { _allSubresourcesSame = 1; _resourceState = state; #if BUILD_DEBUG for (int32 i = 0; i < _subresourceState.Count(); i++) _subresourceState[i] = InvalidState; #endif } void SetSubresourceState(int32 subresourceIndex, StateType state) { // Check if use single state for the whole resource if (subresourceIndex == -1 || _subresourceState.Count() <= 1) { SetResourceState(state); } else { ASSERT(subresourceIndex < static_cast(_subresourceState.Count())); // Transition for all sub-resources if (_allSubresourcesSame) { for (int32 i = 0; i < _subresourceState.Count(); i++) _subresourceState[i] = _resourceState; _allSubresourcesSame = 0; #if BUILD_DEBUG _resourceState = InvalidState; #endif } _subresourceState[subresourceIndex] = state; } } };