| /* |
| * Copyright (c) 2018-2021, Intel Corporation |
| * |
| * Permission is hereby granted, free of charge, to any person obtaining a |
| * copy of this software and associated documentation files (the "Software"), |
| * to deal in the Software without restriction, including without limitation |
| * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
| * and/or sell copies of the Software, and to permit persons to whom the |
| * Software is furnished to do so, subject to the following conditions: |
| * |
| * The above copyright notice and this permission notice shall be included |
| * in all copies or substantial portions of the Software. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
| * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
| * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR |
| * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
| * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
| * OTHER DEALINGS IN THE SOFTWARE. |
| */ |
| //! |
| //! \file vp_resource_manager.cpp |
| //! \brief The source file of the base class of vp resource manager |
| //! \details all the vp resources will be traced here for usages using intermeida |
| //! surfaces. |
| //! |
| #include "vp_resource_manager.h" |
| #include "vp_vebox_cmd_packet.h" |
| #include "sw_filter_pipe.h" |
| #include "vp_utils.h" |
| #include "vp_platform_interface.h" |
| |
| using namespace std; |
| namespace vp |
| { |
| |
| #define VP_SAME_SAMPLE_THRESHOLD 0 |
| |
| inline bool IsInterleaveFirstField(VPHAL_SAMPLE_TYPE sampleType) |
| { |
| VP_FUNC_CALL(); |
| return ((sampleType == SAMPLE_INTERLEAVED_ODD_FIRST_BOTTOM_FIELD) || |
| (sampleType == SAMPLE_INTERLEAVED_EVEN_FIRST_TOP_FIELD) || |
| (sampleType == SAMPLE_SINGLE_TOP_FIELD)); |
| } |
| |
| extern const VEBOX_SPATIAL_ATTRIBUTES_CONFIGURATION g_cInit_VEBOX_SPATIAL_ATTRIBUTES_CONFIGURATIONS = |
| { |
| // DWORD 0 |
| { |
| {NOISE_BLF_RANGE_THRESHOLD_S0_DEFAULT}, // RangeThrStart0 |
| }, |
| |
| // DWORD 1 |
| { |
| {NOISE_BLF_RANGE_THRESHOLD_S1_DEFAULT}, // RangeThrStart1 |
| }, |
| |
| // DWORD 2 |
| { |
| {NOISE_BLF_RANGE_THRESHOLD_S2_DEFAULT}, // RangeThrStart2 |
| }, |
| |
| // DWORD 3 |
| { |
| {NOISE_BLF_RANGE_THRESHOLD_S3_DEFAULT}, // RangeThrStart3 |
| }, |
| |
| // DWORD 4 |
| { |
| {NOISE_BLF_RANGE_THRESHOLD_S4_DEFAULT}, // RangeThrStart4 |
| }, |
| |
| // DWORD 5 |
| { |
| {NOISE_BLF_RANGE_THRESHOLD_S5_DEFAULT}, // RangeThrStart5 |
| }, |
| |
| // DWORD 6 |
| { |
| {0}, // Reserved |
| }, |
| |
| // DWORD 7 |
| { |
| {0}, // Reserved |
| }, |
| |
| // DWORD 8 |
| { |
| {NOISE_BLF_RANGE_WGTS0_DEFAULT}, // RangeWgt0 |
| }, |
| |
| // DWORD 9 |
| { |
| {NOISE_BLF_RANGE_WGTS1_DEFAULT}, // RangeWgt1 |
| }, |
| |
| // DWORD 10 |
| { |
| {NOISE_BLF_RANGE_WGTS2_DEFAULT}, // RangeWgt2 |
| }, |
| |
| // DWORD 11 |
| { |
| {NOISE_BLF_RANGE_WGTS3_DEFAULT}, // RangeWgt3 |
| }, |
| |
| // DWORD 12 |
| { |
| {NOISE_BLF_RANGE_WGTS4_DEFAULT}, // RangeWgt4 |
| }, |
| |
| // DWORD 13 |
| { |
| {NOISE_BLF_RANGE_WGTS5_DEFAULT}, // RangeWgt5 |
| }, |
| |
| // DWORD 14 |
| { |
| {0}, // Reserved |
| }, |
| |
| // DWORD 15 |
| { |
| {0}, // Reserved |
| }, |
| |
| // DWORD 16 - 41: DistWgt[5][5] |
| { |
| {NOISE_BLF_DISTANCE_WGTS00_DEFAULT, NOISE_BLF_DISTANCE_WGTS01_DEFAULT, NOISE_BLF_DISTANCE_WGTS02_DEFAULT, NOISE_BLF_DISTANCE_WGTS01_DEFAULT, NOISE_BLF_DISTANCE_WGTS00_DEFAULT}, |
| {NOISE_BLF_DISTANCE_WGTS10_DEFAULT, NOISE_BLF_DISTANCE_WGTS11_DEFAULT, NOISE_BLF_DISTANCE_WGTS12_DEFAULT, NOISE_BLF_DISTANCE_WGTS11_DEFAULT, NOISE_BLF_DISTANCE_WGTS10_DEFAULT}, |
| {NOISE_BLF_DISTANCE_WGTS20_DEFAULT, NOISE_BLF_DISTANCE_WGTS21_DEFAULT, NOISE_BLF_DISTANCE_WGTS22_DEFAULT, NOISE_BLF_DISTANCE_WGTS21_DEFAULT, NOISE_BLF_DISTANCE_WGTS20_DEFAULT}, |
| {NOISE_BLF_DISTANCE_WGTS10_DEFAULT, NOISE_BLF_DISTANCE_WGTS11_DEFAULT, NOISE_BLF_DISTANCE_WGTS12_DEFAULT, NOISE_BLF_DISTANCE_WGTS11_DEFAULT, NOISE_BLF_DISTANCE_WGTS10_DEFAULT}, |
| {NOISE_BLF_DISTANCE_WGTS00_DEFAULT, NOISE_BLF_DISTANCE_WGTS01_DEFAULT, NOISE_BLF_DISTANCE_WGTS02_DEFAULT, NOISE_BLF_DISTANCE_WGTS01_DEFAULT, NOISE_BLF_DISTANCE_WGTS00_DEFAULT}, |
| }, |
| |
| // Padding |
| { |
| 0, // Padding |
| 0, // Padding |
| 0, // Padding |
| 0, // Padding |
| 0, // Padding |
| 0, // Padding |
| 0, // Padding |
| } |
| }; |
| |
| VpResourceManager::VpResourceManager(MOS_INTERFACE &osInterface, VpAllocator &allocator, VphalFeatureReport &reporting, vp::VpPlatformInterface &vpPlatformInterface) |
| : m_osInterface(osInterface), m_allocator(allocator), m_reporting(reporting), m_vpPlatformInterface(vpPlatformInterface) |
| { |
| InitSurfaceConfigMap(); |
| } |
| |
| VpResourceManager::~VpResourceManager() |
| { |
| // Clean all intermedia Resource |
| DestoryVeboxOutputSurface(); |
| DestoryVeboxDenoiseOutputSurface(); |
| |
| for (uint32_t i = 0; i < VP_NUM_STMM_SURFACES; i++) |
| { |
| if (m_veboxSTMMSurface[i]) |
| { |
| m_allocator.DestroyVpSurface(m_veboxSTMMSurface[i]); |
| } |
| } |
| |
| if (m_veboxStatisticsSurface) |
| { |
| m_allocator.DestroyVpSurface(m_veboxStatisticsSurface); |
| } |
| |
| if (m_veboxRgbHistogram) |
| { |
| m_allocator.DestroyVpSurface(m_veboxRgbHistogram); |
| } |
| |
| if (m_veboxDNTempSurface) |
| { |
| m_allocator.DestroyVpSurface(m_veboxDNTempSurface); |
| } |
| |
| if (m_veboxDNSpatialConfigSurface) |
| { |
| m_allocator.DestroyVpSurface(m_veboxDNSpatialConfigSurface); |
| } |
| |
| if (m_vebox3DLookUpTables) |
| { |
| m_allocator.DestroyVpSurface(m_vebox3DLookUpTables); |
| } |
| |
| while (!m_intermediaSurfaces.empty()) |
| { |
| VP_SURFACE * surf = m_intermediaSurfaces.back(); |
| m_allocator.DestroyVpSurface(surf); |
| m_intermediaSurfaces.pop_back(); |
| } |
| |
| m_allocator.CleanRecycler(); |
| } |
| |
| void VpResourceManager::CleanTempSurfaces() |
| { |
| VP_FUNC_CALL(); |
| |
| while (!m_tempSurface.empty()) |
| { |
| auto it = m_tempSurface.begin(); |
| m_allocator.DestroyVpSurface(it->second); |
| m_tempSurface.erase(it); |
| } |
| } |
| |
| MOS_STATUS VpResourceManager::OnNewFrameProcessStart(SwFilterPipe &pipe) |
| { |
| VP_FUNC_CALL(); |
| |
| VP_SURFACE *inputSurface = pipe.GetSurface(true, 0); |
| VP_SURFACE *outputSurface = pipe.GetSurface(false, 0); |
| SwFilter *diFilter = pipe.GetSwFilter(true, 0, FeatureTypeDi); |
| |
| if (nullptr == inputSurface && nullptr == outputSurface) |
| { |
| VP_PUBLIC_ASSERTMESSAGE("Both input and output surface being nullptr!"); |
| VP_PUBLIC_CHK_STATUS_RETURN(MOS_STATUS_INVALID_PARAMETER); |
| } |
| |
| if (0 != m_currentPipeIndex) |
| { |
| VP_PUBLIC_ASSERTMESSAGE("m_currentPipeIndex(%d) is not 0. May caused by OnNewFrameProcessEnd not paired with OnNewFrameProcessStart!"); |
| VP_PUBLIC_CHK_STATUS_RETURN(MOS_STATUS_INVALID_PARAMETER); |
| } |
| |
| VP_SURFACE *pastSurface = pipe.GetPastSurface(0); |
| VP_SURFACE *futureSurface = pipe.GetFutureSurface(0); |
| |
| int32_t currentFrameId = inputSurface ? inputSurface->FrameID : (outputSurface ? outputSurface->FrameID : 0); |
| int32_t pastFrameId = pastSurface ? pastSurface->FrameID : 0; |
| int32_t futureFrameId = futureSurface ? futureSurface->FrameID : 0; |
| |
| m_currentFrameIds.valid = true; |
| m_currentFrameIds.diEnabled = nullptr != diFilter; |
| m_currentFrameIds.currentFrameId = currentFrameId; |
| m_currentFrameIds.pastFrameId = pastFrameId; |
| m_currentFrameIds.futureFrameId = futureFrameId; |
| m_currentFrameIds.pastFrameAvailable = pastSurface ? true : false; |
| m_currentFrameIds.futureFrameAvailable = futureSurface ? true : false; |
| |
| // Only set sameSamples flag DI enabled frames. |
| if (m_pastFrameIds.valid && m_currentFrameIds.pastFrameAvailable && |
| m_pastFrameIds.diEnabled && m_currentFrameIds.diEnabled) |
| { |
| m_sameSamples = |
| WITHIN_BOUNDS( |
| m_currentFrameIds.currentFrameId - m_pastFrameIds.currentFrameId, |
| -VP_SAME_SAMPLE_THRESHOLD, |
| VP_SAME_SAMPLE_THRESHOLD) && |
| WITHIN_BOUNDS( |
| m_currentFrameIds.pastFrameId - m_pastFrameIds.pastFrameId, |
| -VP_SAME_SAMPLE_THRESHOLD, |
| VP_SAME_SAMPLE_THRESHOLD); |
| |
| if (m_sameSamples) |
| { |
| m_outOfBound = false; |
| } |
| else |
| { |
| m_outOfBound = |
| OUT_OF_BOUNDS( |
| m_currentFrameIds.pastFrameId - m_pastFrameIds.currentFrameId, |
| -VP_SAME_SAMPLE_THRESHOLD, |
| VP_SAME_SAMPLE_THRESHOLD); |
| } |
| } |
| // bSameSamples flag also needs to be set for no reference case |
| else if (m_pastFrameIds.valid && !m_currentFrameIds.pastFrameAvailable && |
| m_pastFrameIds.diEnabled && m_currentFrameIds.diEnabled) |
| { |
| m_sameSamples = |
| WITHIN_BOUNDS( |
| m_currentFrameIds.currentFrameId - m_pastFrameIds.currentFrameId, |
| -VP_SAME_SAMPLE_THRESHOLD, |
| VP_SAME_SAMPLE_THRESHOLD); |
| m_outOfBound = false; |
| } |
| else |
| { |
| m_sameSamples = false; |
| m_outOfBound = false; |
| } |
| |
| if (inputSurface) |
| { |
| m_maxSrcRect.right = MOS_MAX(m_maxSrcRect.right, inputSurface->rcSrc.right); |
| m_maxSrcRect.bottom = MOS_MAX(m_maxSrcRect.bottom, inputSurface->rcSrc.bottom); |
| } |
| |
| // Swap buffers for next iteration |
| if (!m_sameSamples) |
| { |
| m_currentDnOutput = (m_currentDnOutput + 1) & 1; |
| m_currentStmmIndex = (m_currentStmmIndex + 1) & 1; |
| } |
| |
| m_pastFrameIds = m_currentFrameIds; |
| |
| return MOS_STATUS_SUCCESS; |
| } |
| |
| void VpResourceManager::OnNewFrameProcessEnd() |
| { |
| VP_FUNC_CALL(); |
| m_allocator.CleanRecycler(); |
| m_currentPipeIndex = 0; |
| CleanTempSurfaces(); |
| } |
| |
| void VpResourceManager::InitSurfaceConfigMap() |
| { |
| VP_FUNC_CALL(); |
| ///* _b64DI |
| // | _sfcEnable |
| // | | _sameSample |
| // | | | _outOfBound |
| // | | | | _pastRefAvailable |
| // | | | | | _futureRefAvailable |
| // | | | | | | _firstDiField |
| // | | | | | | | _currentInputSurface |
| // | | | | | | | | _pastInputSurface |
| // | | | | | | | | | _currentOutputSurface |
| // | | | | | | | | | | _pastOutputSurface*/ |
| // | | | | | | | | | | | */ |
| AddSurfaceConfig(true, true, false, false, true, false, true, VEBOX_SURFACE_INPUT, VEBOX_SURFACE_PAST_REF, VEBOX_SURFACE_FRAME1, VEBOX_SURFACE_FRAME0); |
| AddSurfaceConfig(true, true, true, false, true, false, false, VEBOX_SURFACE_FRAME1, VEBOX_SURFACE_NULL, VEBOX_SURFACE_NULL, VEBOX_SURFACE_NULL); |
| AddSurfaceConfig(true, true, false, false, false, false, true, VEBOX_SURFACE_INPUT, VEBOX_SURFACE_NULL, VEBOX_SURFACE_FRAME1, VEBOX_SURFACE_NULL); |
| AddSurfaceConfig(true, true, false, false, false, false, false, VEBOX_SURFACE_INPUT, VEBOX_SURFACE_NULL, VEBOX_SURFACE_FRAME1, VEBOX_SURFACE_NULL); |
| AddSurfaceConfig(true, true, true, false, false, false, true, VEBOX_SURFACE_INPUT, VEBOX_SURFACE_NULL, VEBOX_SURFACE_FRAME1, VEBOX_SURFACE_NULL); |
| AddSurfaceConfig(true, true, true, false, false, false, false, VEBOX_SURFACE_INPUT, VEBOX_SURFACE_NULL, VEBOX_SURFACE_FRAME1, VEBOX_SURFACE_NULL); |
| } |
| |
| uint32_t VpResourceManager::GetHistogramSurfaceSize(VP_EXECUTE_CAPS& caps, uint32_t inputWidth, uint32_t inputHeight) |
| { |
| VP_FUNC_CALL(); |
| |
| // Allocate Rgb Histogram surface---------------------------------------------- |
| // Size of RGB histograms, 1 set for each slice. For single slice, other set will be 0 |
| uint32_t dwSize = VP_VEBOX_RGB_HISTOGRAM_SIZE; |
| dwSize += VP_VEBOX_RGB_ACE_HISTOGRAM_SIZE_RESERVED; |
| // Size of ACE histograms, 1 set for each slice. For single slice, other set will be 0 |
| dwSize += VP_VEBOX_ACE_HISTOGRAM_SIZE_PER_FRAME_PER_SLICE * // Ace histogram size per slice |
| VP_NUM_FRAME_PREVIOUS_CURRENT * // Ace for Prev + Curr |
| VP_VEBOX_HISTOGRAM_SLICES_COUNT; // Total number of slices |
| return dwSize; |
| } |
| |
| MOS_STATUS VpResourceManager::GetResourceHint(std::vector<FeatureType> &featurePool, SwFilterPipe& executedFilters, RESOURCE_ASSIGNMENT_HINT &hint) |
| { |
| VP_FUNC_CALL(); |
| |
| uint32_t index = 0; |
| SwFilterSubPipe *inputPipe = executedFilters.GetSwFilterPrimaryPipe(index); |
| |
| // only process Primary surface |
| VP_PUBLIC_CHK_NULL_RETURN(inputPipe); |
| for (auto filterID : featurePool) |
| { |
| SwFilter* feature = (SwFilter*)inputPipe->GetSwFilter(FeatureType(filterID)); |
| if (feature) |
| { |
| VP_PUBLIC_CHK_STATUS_RETURN(feature->SetResourceAssignmentHint(hint)); |
| } |
| } |
| return MOS_STATUS_SUCCESS; |
| } |
| |
| struct VP_SURFACE_PARAMS |
| { |
| uint32_t width; |
| uint32_t height; |
| MOS_FORMAT format; |
| MOS_TILE_TYPE tileType; |
| MOS_RESOURCE_MMC_MODE surfCompressionMode = MOS_MMC_DISABLED; |
| bool surfCompressible = false; |
| VPHAL_CSPACE colorSpace; |
| RECT rcSrc; //!< Source rectangle |
| RECT rcDst; //!< Destination rectangle |
| RECT rcMaxSrc; //!< Max source rectangle |
| VPHAL_SAMPLE_TYPE sampleType; |
| }; |
| |
| MOS_STATUS VpResourceManager::GetIntermediaOutputSurfaceParams(VP_SURFACE_PARAMS ¶ms, SwFilterPipe &executedFilters) |
| { |
| VP_FUNC_CALL(); |
| |
| SwFilterCsc *csc = dynamic_cast<SwFilterCsc *>(executedFilters.GetSwFilter(true, 0, FeatureType::FeatureTypeCsc)); |
| SwFilterScaling *scaling = dynamic_cast<SwFilterScaling *>(executedFilters.GetSwFilter(true, 0, FeatureType::FeatureTypeScaling)); |
| SwFilterRotMir *rotMir = dynamic_cast<SwFilterRotMir *>(executedFilters.GetSwFilter(true, 0, FeatureType::FeatureTypeRotMir)); |
| SwFilterDeinterlace *di = dynamic_cast<SwFilterDeinterlace *>(executedFilters.GetSwFilter(true, 0, FeatureType::FeatureTypeDi)); |
| VP_SURFACE *inputSurface = executedFilters.GetSurface(true, 0); |
| |
| VP_PUBLIC_CHK_NULL_RETURN(inputSurface); |
| |
| if (scaling) |
| { |
| params.width = scaling->GetSwFilterParams().output.dwWidth; |
| params.height = scaling->GetSwFilterParams().output.dwHeight; |
| params.sampleType = scaling->GetSwFilterParams().output.sampleType; |
| params.rcSrc = scaling->GetSwFilterParams().output.rcSrc; |
| params.rcDst = scaling->GetSwFilterParams().output.rcDst; |
| params.rcMaxSrc = scaling->GetSwFilterParams().output.rcMaxSrc; |
| } |
| else |
| { |
| params.width = inputSurface->osSurface->dwWidth; |
| params.height = inputSurface->osSurface->dwHeight; |
| params.sampleType = di ? SAMPLE_PROGRESSIVE : inputSurface->SampleType; |
| params.rcSrc = inputSurface->rcSrc; |
| params.rcDst = inputSurface->rcDst; |
| params.rcMaxSrc = inputSurface->rcMaxSrc; |
| } |
| |
| // Do not use rotatoin flag in scaling swfilter as it has not been initialized here. |
| // It will be initialized during pipe update after resource being assigned. |
| if (rotMir && |
| (rotMir->GetSwFilterParams().rotation == VPHAL_ROTATION_90 || |
| rotMir->GetSwFilterParams().rotation == VPHAL_ROTATION_270 || |
| rotMir->GetSwFilterParams().rotation == VPHAL_ROTATE_90_MIRROR_VERTICAL || |
| rotMir->GetSwFilterParams().rotation == VPHAL_ROTATE_90_MIRROR_HORIZONTAL)) |
| { |
| swap(params.width, params.height); |
| RECT tmp = params.rcSrc; |
| RECT_ROTATE(params.rcSrc, tmp); |
| tmp = params.rcDst; |
| RECT_ROTATE(params.rcDst, tmp); |
| tmp = params.rcMaxSrc; |
| RECT_ROTATE(params.rcMaxSrc, tmp); |
| } |
| |
| if (csc) |
| { |
| params.format = csc->GetSwFilterParams().formatOutput; |
| params.colorSpace = csc->GetSwFilterParams().output.colorSpace; |
| } |
| else |
| { |
| params.format = inputSurface->osSurface->Format; |
| params.colorSpace = inputSurface->ColorSpace; |
| } |
| params.tileType = MOS_TILE_Y; |
| params.surfCompressionMode = MOS_MMC_DISABLED; |
| params.surfCompressible = false; |
| |
| return MOS_STATUS_SUCCESS; |
| } |
| |
| MOS_STATUS VpResourceManager::AssignIntermediaSurface(SwFilterPipe &executedFilters) |
| { |
| VP_FUNC_CALL(); |
| |
| VP_SURFACE* outputSurface = executedFilters.GetSurface(false, 0); |
| if (outputSurface) |
| { |
| // No need intermedia surface. |
| return MOS_STATUS_SUCCESS; |
| } |
| |
| while (m_currentPipeIndex >= m_intermediaSurfaces.size()) |
| { |
| m_intermediaSurfaces.push_back(nullptr); |
| } |
| VP_SURFACE_PARAMS params = {}; |
| bool allocated = false; |
| // Get surface parameter. |
| GetIntermediaOutputSurfaceParams(params, executedFilters); |
| |
| VP_PUBLIC_CHK_STATUS_RETURN(m_allocator.ReAllocateSurface( |
| m_intermediaSurfaces[m_currentPipeIndex], |
| "IntermediaSurface", |
| params.format, |
| MOS_GFXRES_2D, |
| params.tileType, |
| params.width, |
| params.height, |
| params.surfCompressible, |
| params.surfCompressionMode, |
| allocated, |
| false, |
| IsDeferredResourceDestroyNeeded(), |
| MOS_HW_RESOURCE_USAGE_VP_INTERNAL_READ_WRITE_RENDER)); |
| |
| VP_PUBLIC_CHK_NULL_RETURN(m_intermediaSurfaces[m_currentPipeIndex]); |
| |
| m_intermediaSurfaces[m_currentPipeIndex]->ColorSpace = params.colorSpace; |
| m_intermediaSurfaces[m_currentPipeIndex]->rcDst = params.rcDst; |
| m_intermediaSurfaces[m_currentPipeIndex]->rcSrc = params.rcSrc; |
| m_intermediaSurfaces[m_currentPipeIndex]->rcMaxSrc = params.rcMaxSrc; |
| m_intermediaSurfaces[m_currentPipeIndex]->SampleType = params.sampleType; |
| |
| VP_SURFACE *output = m_allocator.AllocateVpSurface(*m_intermediaSurfaces[m_currentPipeIndex]); |
| VP_PUBLIC_CHK_NULL_RETURN(output); |
| |
| executedFilters.AddSurface(output, false, 0); |
| |
| return MOS_STATUS_SUCCESS; |
| } |
| |
| VP_SURFACE * VpResourceManager::GetCopyInstOfExtSurface(VP_SURFACE* surf) |
| { |
| VP_FUNC_CALL(); |
| |
| if (nullptr == surf || 0 == surf->GetAllocationHandle()) |
| { |
| return nullptr; |
| } |
| auto it = m_tempSurface.find(surf->GetAllocationHandle()); |
| if (it != m_tempSurface.end()) |
| { |
| return it->second; |
| } |
| VP_SURFACE *surface = m_allocator.AllocateVpSurface(*surf); |
| if (surface) |
| { |
| m_tempSurface.insert(make_pair(surf->GetAllocationHandle(), surface)); |
| } |
| else |
| { |
| VP_PUBLIC_ASSERTMESSAGE("Allocate temp surface faild!"); |
| } |
| |
| return surface; |
| } |
| |
| MOS_STATUS VpResourceManager::AssignRenderResource(VP_EXECUTE_CAPS &caps, VP_SURFACE *inputSurface, VP_SURFACE *outputSurface, RESOURCE_ASSIGNMENT_HINT resHint, VP_SURFACE_SETTING &surfSetting) |
| { |
| VP_FUNC_CALL(); |
| |
| surfSetting.surfGroup.insert(std::make_pair(SurfaceTypeRenderInput, inputSurface)); |
| VP_PUBLIC_CHK_STATUS_RETURN(AssignVeboxResourceForRender(caps, inputSurface, resHint, surfSetting)); |
| return MOS_STATUS_SUCCESS; |
| } |
| |
| MOS_STATUS VpResourceManager::AssignVeboxResourceForRender(VP_EXECUTE_CAPS &caps, VP_SURFACE *inputSurface, RESOURCE_ASSIGNMENT_HINT resHint, VP_SURFACE_SETTING &surfSetting) |
| { |
| VP_FUNC_CALL(); |
| |
| if (!caps.bRender) |
| { |
| return MOS_STATUS_INVALID_PARAMETER; |
| } |
| |
| return MOS_STATUS_SUCCESS; |
| } |
| |
| MOS_STATUS VpResourceManager::AssignExecuteResource(std::vector<FeatureType> &featurePool, VP_EXECUTE_CAPS& caps, SwFilterPipe &executedFilters) |
| { |
| VP_FUNC_CALL(); |
| |
| VP_SURFACE *inputSurface = GetCopyInstOfExtSurface(executedFilters.GetSurface(true, 0)); |
| VP_SURFACE *outputSurface = GetCopyInstOfExtSurface(executedFilters.GetSurface(false, 0)); |
| VP_SURFACE *pastSurface = GetCopyInstOfExtSurface(executedFilters.GetPastSurface(0)); |
| VP_SURFACE *futureSurface = GetCopyInstOfExtSurface(executedFilters.GetFutureSurface(0)); |
| |
| RESOURCE_ASSIGNMENT_HINT resHint = {}; |
| |
| VP_PUBLIC_CHK_STATUS_RETURN(GetResourceHint(featurePool, executedFilters, resHint)); |
| |
| if (nullptr == outputSurface && IsOutputSurfaceNeeded(caps)) |
| { |
| VP_PUBLIC_CHK_STATUS_RETURN(AssignIntermediaSurface(executedFilters)); |
| outputSurface = GetCopyInstOfExtSurface(executedFilters.GetSurface(false, 0)); |
| VP_PUBLIC_CHK_NULL_RETURN(outputSurface); |
| } |
| |
| VP_PUBLIC_CHK_STATUS_RETURN(AssignExecuteResource(caps, inputSurface, outputSurface, |
| pastSurface, futureSurface, resHint, executedFilters.GetSurfacesSetting())); |
| ++m_currentPipeIndex; |
| return MOS_STATUS_SUCCESS; |
| } |
| |
| MOS_STATUS VpResourceManager::AssignExecuteResource(VP_EXECUTE_CAPS& caps, VP_SURFACE *inputSurface, VP_SURFACE *outputSurface, |
| VP_SURFACE *pastSurface, VP_SURFACE *futureSurface, RESOURCE_ASSIGNMENT_HINT resHint, VP_SURFACE_SETTING &surfSetting) |
| { |
| VP_FUNC_CALL(); |
| |
| surfSetting.Clean(); |
| |
| if (caps.bVebox || caps.bDnKernelUpdate) |
| { |
| // Create Vebox Resources |
| VP_PUBLIC_CHK_STATUS_RETURN(AssignVeboxResource(caps, inputSurface, outputSurface, pastSurface, futureSurface, resHint, surfSetting)); |
| } |
| |
| if (caps.bRender) |
| { |
| VP_PUBLIC_CHK_STATUS_RETURN(AssignRenderResource(caps, inputSurface, outputSurface, resHint, surfSetting)); |
| } |
| |
| return MOS_STATUS_SUCCESS; |
| } |
| |
| MOS_STATUS GetVeboxOutputParams(VP_EXECUTE_CAPS &executeCaps, MOS_FORMAT inputFormat, MOS_TILE_TYPE inputTileType, MOS_FORMAT outputFormat, |
| MOS_FORMAT &veboxOutputFormat, MOS_TILE_TYPE &veboxOutputTileType) |
| { |
| VP_FUNC_CALL(); |
| |
| // Vebox Chroma Co-Sited downsampleing is part of VEO. It only affects format of vebox output surface, but not |
| // affect sfc input format, that's why different logic between GetSfcInputFormat and GetVeboxOutputParams. |
| // Check DI first and downsampling to NV12 if possible to save bandwidth no matter IECP enabled or not. |
| if (executeCaps.bDI || executeCaps.bDiProcess2ndField) |
| { |
| // NV12 will be used if target output is not YUV2 to save bandwidth. |
| if (outputFormat == Format_YUY2) |
| { |
| veboxOutputFormat = Format_YUY2; |
| } |
| else |
| { |
| veboxOutputFormat = Format_NV12; |
| } |
| veboxOutputTileType = MOS_TILE_Y; |
| } |
| else if (executeCaps.bIECP && executeCaps.bCGC && executeCaps.bBt2020ToRGB) |
| { |
| veboxOutputFormat = Format_A8B8G8R8; |
| veboxOutputTileType = inputTileType; |
| } |
| else if (executeCaps.bIECP) |
| { |
| // Upsampling to yuv444 for IECP input/output. |
| // To align with legacy path, need to check whether inputFormat can also be used for IECP case, |
| // in which case IECP down sampling will be applied. |
| veboxOutputFormat = Format_AYUV; |
| veboxOutputTileType = inputTileType; |
| } |
| else |
| { |
| veboxOutputFormat = inputFormat; |
| veboxOutputTileType = inputTileType; |
| } |
| |
| return MOS_STATUS_SUCCESS; |
| } |
| |
| MOS_FORMAT GetSfcInputFormat(VP_EXECUTE_CAPS &executeCaps, MOS_FORMAT inputFormat, VPHAL_CSPACE colorSpaceOutput) |
| { |
| VP_FUNC_CALL(); |
| |
| // Vebox Chroma Co-Sited downsampling is part of VEO. It only affects format of vebox output surface, but not |
| // affect sfc input format, that's why different logic between GetSfcInputFormat and GetVeboxOutputParams. |
| // Check HDR case first, since 3DLUT output is fixed RGB32. |
| // Then Check IECP, since IECP is done after DI, and the vebox downsampling not affect the vebox input. |
| if (executeCaps.bHDR3DLUT) |
| { |
| return IS_COLOR_SPACE_BT2020(colorSpaceOutput) ? Format_R10G10B10A2 : Format_A8B8G8R8; |
| } |
| else if (executeCaps.bIECP && executeCaps.bCGC && executeCaps.bBt2020ToRGB) |
| { |
| // Upsampling to RGB444, and using ABGR as Vebox output |
| return Format_A8B8G8R8; |
| } |
| else if (executeCaps.bIECP) |
| { |
| // Upsampling to yuv444 for IECP input/output. |
| // To align with legacy path, need to check whether inputFormat can also be used for IECP case, |
| // in which case IECP down sampling will be applied. |
| return Format_AYUV; |
| } |
| else if (executeCaps.bDI) |
| { |
| // If the input is 4:2:0, then chroma data is doubled vertically to 4:2:2 |
| // For executeCaps.bDiProcess2ndField, no DI enabled in vebox, so no need |
| // set to YUY2 here. |
| return Format_YUY2; |
| } |
| |
| return inputFormat; |
| } |
| |
| MOS_STATUS VpResourceManager::ReAllocateVeboxOutputSurface(VP_EXECUTE_CAPS& caps, VP_SURFACE *inputSurface, VP_SURFACE *outputSurface, bool &allocated) |
| { |
| VP_FUNC_CALL(); |
| |
| MOS_RESOURCE_MMC_MODE surfCompressionMode = MOS_MMC_DISABLED; |
| bool bSurfCompressible = false; |
| uint32_t i = 0; |
| auto *skuTable = MosInterface::GetSkuTable(m_osInterface.osStreamState); |
| Mos_MemPool memTypeSurfVideoMem = MOS_MEMPOOL_VIDEOMEMORY; |
| |
| VP_PUBLIC_CHK_NULL_RETURN(inputSurface); |
| VP_PUBLIC_CHK_NULL_RETURN(inputSurface->osSurface); |
| VP_PUBLIC_CHK_NULL_RETURN(outputSurface); |
| VP_PUBLIC_CHK_NULL_RETURN(outputSurface->osSurface); |
| |
| if (skuTable && MEDIA_IS_SKU(skuTable, FtrLimitedLMemBar)) |
| { |
| memTypeSurfVideoMem = MOS_MEMPOOL_DEVICEMEMORY; |
| } |
| |
| MOS_FORMAT veboxOutputFormat = inputSurface->osSurface->Format; |
| MOS_TILE_TYPE veboxOutputTileType = inputSurface->osSurface->TileType; |
| |
| VP_PUBLIC_CHK_STATUS_RETURN(GetVeboxOutputParams(caps, inputSurface->osSurface->Format, inputSurface->osSurface->TileType, |
| outputSurface->osSurface->Format, veboxOutputFormat, veboxOutputTileType)); |
| |
| allocated = false; |
| if (IS_VP_VEBOX_DN_ONLY(caps)) |
| { |
| bSurfCompressible = inputSurface->osSurface->bCompressible; |
| surfCompressionMode = inputSurface->osSurface->CompressionMode; |
| } |
| else |
| { |
| bSurfCompressible = true; |
| surfCompressionMode = MOS_MMC_MC; |
| } |
| |
| if (m_currentFrameIds.pastFrameAvailable && m_currentFrameIds.futureFrameAvailable) |
| { |
| // Not switch back to 2 after being set to 4. |
| m_veboxOutputCount = 4; |
| } |
| |
| for (i = 0; i < m_veboxOutputCount; i++) |
| { |
| VP_PUBLIC_CHK_STATUS_RETURN(m_allocator.ReAllocateSurface( |
| m_veboxOutput[i], |
| "VeboxSurfaceOutput", |
| veboxOutputFormat, |
| MOS_GFXRES_2D, |
| veboxOutputTileType, |
| inputSurface->osSurface->dwWidth, |
| inputSurface->osSurface->dwHeight, |
| bSurfCompressible, |
| surfCompressionMode, |
| allocated, |
| false, |
| IsDeferredResourceDestroyNeeded(), |
| MOS_HW_RESOURCE_USAGE_VP_OUTPUT_PICTURE_FF, |
| MOS_TILE_UNSET_GMM, |
| memTypeSurfVideoMem, |
| MOS_MEMPOOL_DEVICEMEMORY == memTypeSurfVideoMem)); |
| |
| m_veboxOutput[i]->ColorSpace = inputSurface->ColorSpace; |
| m_veboxOutput[i]->rcDst = inputSurface->rcDst; |
| m_veboxOutput[i]->rcSrc = inputSurface->rcSrc; |
| m_veboxOutput[i]->rcMaxSrc = inputSurface->rcMaxSrc; |
| |
| m_veboxOutput[i]->SampleType = SAMPLE_PROGRESSIVE; |
| } |
| |
| if (allocated) |
| { |
| // Report Compress Status |
| if (m_veboxOutput[0]->osSurface) |
| { |
| m_reporting.FFDICompressible = m_veboxOutput[0]->osSurface->bIsCompressed; |
| m_reporting.FFDICompressMode = (uint8_t)m_veboxOutput[0]->osSurface->CompressionMode; |
| } |
| } |
| |
| return MOS_STATUS_SUCCESS; |
| } |
| |
| MOS_STATUS VpResourceManager::ReAllocateVeboxDenoiseOutputSurface(VP_EXECUTE_CAPS& caps, VP_SURFACE *inputSurface, bool &allocated) |
| { |
| VP_FUNC_CALL(); |
| |
| MOS_RESOURCE_MMC_MODE surfCompressionMode = MOS_MMC_DISABLED; |
| bool bSurfCompressible = false; |
| MOS_TILE_MODE_GMM tileModeByForce = MOS_TILE_UNSET_GMM; |
| auto * skuTable = MosInterface::GetSkuTable(m_osInterface.osStreamState); |
| Mos_MemPool memTypeSurfVideoMem = MOS_MEMPOOL_VIDEOMEMORY; |
| |
| VP_PUBLIC_CHK_NULL_RETURN(inputSurface); |
| VP_PUBLIC_CHK_NULL_RETURN(inputSurface->osSurface); |
| |
| if (skuTable) |
| { |
| if (MEDIA_IS_SKU(skuTable, FtrMediaTile64)) |
| { |
| tileModeByForce = MOS_TILE_64_GMM; |
| } |
| |
| if (MEDIA_IS_SKU(skuTable, FtrLimitedLMemBar)) |
| { |
| memTypeSurfVideoMem = MOS_MEMPOOL_DEVICEMEMORY; |
| } |
| } |
| |
| allocated = false; |
| if (IS_VP_VEBOX_DN_ONLY(caps)) |
| { |
| bSurfCompressible = inputSurface->osSurface->bCompressible; |
| surfCompressionMode = inputSurface->osSurface->CompressionMode; |
| } |
| else |
| { |
| bSurfCompressible = true; |
| surfCompressionMode = MOS_MMC_MC; |
| } |
| |
| for (uint32_t i = 0; i < VP_NUM_DN_SURFACES; i++) |
| { |
| VP_PUBLIC_CHK_STATUS_RETURN(m_allocator.ReAllocateSurface( |
| m_veboxDenoiseOutput[i], |
| "VeboxFFDNSurface", |
| inputSurface->osSurface->Format, |
| MOS_GFXRES_2D, |
| inputSurface->osSurface->TileType, |
| inputSurface->osSurface->dwWidth, |
| inputSurface->osSurface->dwHeight, |
| bSurfCompressible, |
| surfCompressionMode, |
| allocated, |
| false, |
| IsDeferredResourceDestroyNeeded(), |
| MOS_HW_RESOURCE_USAGE_VP_INPUT_REFERENCE_FF, |
| tileModeByForce, |
| memTypeSurfVideoMem, |
| MOS_MEMPOOL_DEVICEMEMORY == memTypeSurfVideoMem)); |
| |
| // if allocated, pVeboxState->PastSurface is not valid for DN reference. |
| if (allocated) |
| { |
| // If DI is enabled, try to use app's reference if provided |
| if (caps.bRefValid && caps.bDI) |
| { |
| //CopySurfaceValue(pVeboxState->m_previousSurface, pVeboxState->m_currentSurface->pBwdRef); |
| } |
| else |
| { |
| caps.bRefValid = false; |
| } |
| // Report Compress Status |
| if (m_veboxDenoiseOutput[i]->osSurface) |
| { |
| m_reporting.FFDNCompressible = m_veboxDenoiseOutput[i]->osSurface->bIsCompressed; |
| m_reporting.FFDNCompressMode = (uint8_t)m_veboxDenoiseOutput[i]->osSurface->CompressionMode; |
| } |
| } |
| else |
| { |
| caps.bRefValid = true; |
| } |
| |
| // DN's output format should be same to input |
| m_veboxDenoiseOutput[i]->SampleType = |
| inputSurface->SampleType; |
| |
| // Set Colorspace of FFDN |
| m_veboxDenoiseOutput[i]->ColorSpace = inputSurface->ColorSpace; |
| |
| // Copy FrameID and parameters, as DN output will be used as next blt's current |
| m_veboxDenoiseOutput[i]->FrameID = inputSurface->FrameID; |
| |
| // Place Holder to update report for debug purpose |
| } |
| return MOS_STATUS_SUCCESS; |
| } |
| |
| //! |
| //! \brief Vebox initialize STMM History |
| //! \details Initialize STMM History surface |
| //! Description: |
| //! This function is used by VEBox for initializing |
| //! the STMM surface. The STMM / Denoise history is a custom surface used |
| //! for both input and output. Each cache line contains data for 4 4x4s. |
| //! The STMM for each 4x4 is 8 bytes, while the denoise history is 1 byte |
| //! and the chroma denoise history is 1 byte for each U and V. |
| //! Byte Data\n |
| //! 0 STMM for 2 luma values at luma Y=0, X=0 to 1\n |
| //! 1 STMM for 2 luma values at luma Y=0, X=2 to 3\n |
| //! 2 Luma Denoise History for 4x4 at 0,0\n |
| //! 3 Not Used\n |
| //! 4-5 STMM for luma from X=4 to 7\n |
| //! 6 Luma Denoise History for 4x4 at 0,4\n |
| //! 7 Not Used\n |
| //! 8-15 Repeat for 4x4s at 0,8 and 0,12\n |
| //! 16 STMM for 2 luma values at luma Y=1,X=0 to 1\n |
| //! 17 STMM for 2 luma values at luma Y=1, X=2 to 3\n |
| //! 18 U Chroma Denoise History\n |
| //! 19 Not Used\n |
| //! 20-31 Repeat for 3 4x4s at 1,4, 1,8 and 1,12\n |
| //! 32 STMM for 2 luma values at luma Y=2,X=0 to 1\n |
| //! 33 STMM for 2 luma values at luma Y=2, X=2 to 3\n |
| //! 34 V Chroma Denoise History\n |
| //! 35 Not Used\n |
| //! 36-47 Repeat for 3 4x4s at 2,4, 2,8 and 2,12\n |
| //! 48 STMM for 2 luma values at luma Y=3,X=0 to 1\n |
| //! 49 STMM for 2 luma values at luma Y=3, X=2 to 3\n |
| //! 50-51 Not Used\n |
| //! 36-47 Repeat for 3 4x4s at 3,4, 3,8 and 3,12\n |
| //! \param [in] iSurfaceIndex |
| //! Index of STMM surface array |
| //! \return MOS_STATUS |
| //! Return MOS_STATUS_SUCCESS if successful, otherwise failed |
| //! |
| MOS_STATUS VpResourceManager::VeboxInitSTMMHistory(MOS_SURFACE *stmmSurface) |
| { |
| VP_FUNC_CALL(); |
| |
| uint32_t dwSize = 0; |
| int32_t x = 0, y = 0; |
| uint8_t* pByte = nullptr; |
| MOS_LOCK_PARAMS LockFlags; |
| |
| VP_PUBLIC_CHK_NULL_RETURN(stmmSurface); |
| MOS_ZeroMemory(&LockFlags, sizeof(MOS_LOCK_PARAMS)); |
| |
| LockFlags.WriteOnly = 1; |
| LockFlags.TiledAsTiled = 1; // Set TiledAsTiled flag for STMM surface initialization. |
| |
| // Lock the surface for writing |
| pByte = (uint8_t*)m_allocator.Lock( |
| &stmmSurface->OsResource, |
| &LockFlags); |
| VP_PUBLIC_CHK_NULL_RETURN(pByte); |
| |
| dwSize = stmmSurface->dwWidth >> 2; |
| |
| // Fill STMM surface with DN history init values. |
| for (y = 0; y < (int32_t)stmmSurface->dwHeight; y++) |
| { |
| for (x = 0; x < (int32_t)dwSize; x++) |
| { |
| MOS_FillMemory(pByte, 2, DNDI_HISTORY_INITVALUE); |
| // skip denosie history init. |
| pByte += 4; |
| } |
| |
| pByte += stmmSurface->dwPitch - stmmSurface->dwWidth; |
| } |
| |
| // Unlock the surface |
| VP_PUBLIC_CHK_STATUS_RETURN(m_allocator.UnLock(&stmmSurface->OsResource)); |
| return MOS_STATUS_SUCCESS; |
| } |
| |
| // Allocate STMM (Spatial-Temporal Motion Measure) Surfaces |
| MOS_STATUS VpResourceManager::ReAllocateVeboxSTMMSurface(VP_EXECUTE_CAPS& caps, VP_SURFACE *inputSurface, bool &allocated) |
| { |
| VP_FUNC_CALL(); |
| |
| MOS_RESOURCE_MMC_MODE surfCompressionMode = MOS_MMC_DISABLED; |
| bool bSurfCompressible = false; |
| uint32_t i = 0; |
| MOS_TILE_MODE_GMM tileModeByForce = MOS_TILE_UNSET_GMM; |
| auto * skuTable = MosInterface::GetSkuTable(m_osInterface.osStreamState); |
| Mos_MemPool memTypeHistStat = GetHistStatMemType(); |
| |
| VP_PUBLIC_CHK_NULL_RETURN(inputSurface); |
| VP_PUBLIC_CHK_NULL_RETURN(inputSurface->osSurface); |
| |
| if (skuTable && MEDIA_IS_SKU(skuTable, FtrMediaTile64)) |
| { |
| tileModeByForce = MOS_TILE_64_GMM; |
| } |
| |
| allocated = false; |
| for (i = 0; i < VP_NUM_STMM_SURFACES; i++) |
| { |
| VP_PUBLIC_CHK_STATUS_RETURN(m_allocator.ReAllocateSurface( |
| m_veboxSTMMSurface[i], |
| "VeboxSTMMSurface", |
| Format_STMM, |
| MOS_GFXRES_2D, |
| MOS_TILE_Y, |
| inputSurface->osSurface->dwWidth, |
| inputSurface->osSurface->dwHeight, |
| bSurfCompressible, |
| surfCompressionMode, |
| allocated, |
| false, |
| IsDeferredResourceDestroyNeeded(), |
| MOS_HW_RESOURCE_USAGE_VP_INTERNAL_READ_WRITE_FF, |
| tileModeByForce, |
| memTypeHistStat, |
| MOS_MEMPOOL_DEVICEMEMORY == memTypeHistStat)); |
| |
| if (allocated) |
| { |
| VP_PUBLIC_CHK_NULL_RETURN(m_veboxSTMMSurface[i]); |
| if (MOS_MEMPOOL_DEVICEMEMORY != memTypeHistStat) |
| { |
| VP_PUBLIC_CHK_STATUS_RETURN(VeboxInitSTMMHistory(m_veboxSTMMSurface[i]->osSurface)); |
| } |
| // Report Compress Status |
| m_reporting.STMMCompressible = bSurfCompressible; |
| m_reporting.STMMCompressMode = (uint8_t)surfCompressionMode; |
| } |
| } |
| return MOS_STATUS_SUCCESS; |
| } |
| |
| void VpResourceManager::DestoryVeboxOutputSurface() |
| { |
| VP_FUNC_CALL(); |
| |
| for (uint32_t i = 0; i < VP_MAX_NUM_VEBOX_SURFACES; i++) |
| { |
| m_allocator.DestroyVpSurface(m_veboxOutput[i], IsDeferredResourceDestroyNeeded()); |
| } |
| } |
| |
| void VpResourceManager::DestoryVeboxDenoiseOutputSurface() |
| { |
| VP_FUNC_CALL(); |
| |
| for (uint32_t i = 0; i < VP_NUM_DN_SURFACES; i++) |
| { |
| m_allocator.DestroyVpSurface(m_veboxDenoiseOutput[i], IsDeferredResourceDestroyNeeded()); |
| } |
| } |
| |
| void VpResourceManager::DestoryVeboxSTMMSurface() |
| { |
| VP_FUNC_CALL(); |
| |
| // Free DI history buffers (STMM = Spatial-temporal motion measure) |
| for (uint32_t i = 0; i < VP_NUM_STMM_SURFACES; i++) |
| { |
| m_allocator.DestroyVpSurface(m_veboxSTMMSurface[i], IsDeferredResourceDestroyNeeded()); |
| } |
| } |
| |
| uint32_t VpResourceManager::Get3DLutSize() |
| { |
| VP_FUNC_CALL(); |
| |
| return VP_VEBOX_HDR_3DLUT65; |
| } |
| |
| Mos_MemPool VpResourceManager::GetHistStatMemType() |
| { |
| VP_FUNC_CALL(); |
| |
| return MOS_MEMPOOL_VIDEOMEMORY; |
| } |
| |
| MOS_STATUS VpResourceManager::AllocateVeboxResource(VP_EXECUTE_CAPS& caps, VP_SURFACE *inputSurface, VP_SURFACE *outputSurface) |
| { |
| VP_FUNC_CALL(); |
| MOS_FORMAT format; |
| MOS_TILE_TYPE TileType; |
| uint32_t dwWidth; |
| uint32_t dwHeight; |
| uint32_t dwSize; |
| uint32_t i; |
| MOS_RESOURCE_MMC_MODE surfCompressionMode = MOS_MMC_DISABLED; |
| bool bSurfCompressible = false; |
| bool bAllocated = false; |
| uint8_t InitValue = 0; |
| Mos_MemPool memTypeHistStat = GetHistStatMemType(); |
| |
| VP_PUBLIC_CHK_NULL_RETURN(inputSurface); |
| VP_PUBLIC_CHK_NULL_RETURN(inputSurface->osSurface); |
| VP_PUBLIC_CHK_NULL_RETURN(outputSurface); |
| VP_PUBLIC_CHK_NULL_RETURN(outputSurface->osSurface); |
| |
| // change the init value when null hw is enabled |
| if (NullHW::IsEnabled()) |
| { |
| InitValue = 0x80; |
| } |
| |
| if (IS_VP_VEBOX_DN_ONLY(caps)) |
| { |
| bSurfCompressible = inputSurface->osSurface->bCompressible; |
| surfCompressionMode = inputSurface->osSurface->CompressionMode; |
| } |
| else |
| { |
| bSurfCompressible = true; |
| surfCompressionMode = MOS_MMC_MC; |
| } |
| |
| // Decide DN output surface |
| if (VeboxOutputNeeded(caps)) |
| { |
| VP_PUBLIC_CHK_STATUS_RETURN(ReAllocateVeboxOutputSurface(caps, inputSurface, outputSurface, bAllocated)); |
| } |
| else |
| { |
| DestoryVeboxOutputSurface(); |
| } |
| |
| if (VeboxDenoiseOutputNeeded(caps)) |
| { |
| VP_PUBLIC_CHK_STATUS_RETURN(ReAllocateVeboxDenoiseOutputSurface(caps, inputSurface, bAllocated)); |
| if (bAllocated) |
| { |
| m_currentDnOutput = 0; |
| m_pastDnOutputValid = false; |
| } |
| } |
| else |
| { |
| DestoryVeboxDenoiseOutputSurface(); |
| m_pastDnOutputValid = false; |
| } |
| |
| if (VeboxSTMMNeeded(caps, false)) |
| { |
| VP_PUBLIC_CHK_STATUS_RETURN(ReAllocateVeboxSTMMSurface(caps, inputSurface, bAllocated)); |
| if (bAllocated) |
| { |
| m_currentStmmIndex = 0; |
| } |
| } |
| else |
| { |
| DestoryVeboxSTMMSurface(); |
| } |
| |
| #if VEBOX_AUTO_DENOISE_SUPPORTED |
| // Allocate Temp Surface for Vebox Update kernels---------------------------------------- |
| // the surface size is one Page |
| dwSize = MHW_PAGE_SIZE; |
| VP_PUBLIC_CHK_STATUS_RETURN(m_allocator.ReAllocateSurface( |
| m_veboxDNTempSurface, |
| "VeboxDNTempSurface", |
| Format_Buffer, |
| MOS_GFXRES_BUFFER, |
| MOS_TILE_LINEAR, |
| dwSize, |
| 1, |
| false, |
| MOS_MMC_DISABLED, |
| bAllocated, |
| true, |
| IsDeferredResourceDestroyNeeded(), |
| MOS_HW_RESOURCE_USAGE_VP_INTERNAL_READ_WRITE_FF)); |
| |
| // Allocate Spatial Attributes Configuration Surface for DN kernel Gen9+----------- |
| dwSize = MHW_PAGE_SIZE; |
| VP_PUBLIC_CHK_STATUS_RETURN(m_allocator.ReAllocateSurface( |
| m_veboxDNSpatialConfigSurface, |
| "VeboxSpatialAttributesConfigurationSurface", |
| Format_RAW, |
| MOS_GFXRES_BUFFER, |
| MOS_TILE_LINEAR, |
| dwSize, |
| 1, |
| false, |
| MOS_MMC_DISABLED, |
| bAllocated, |
| false, |
| IsDeferredResourceDestroyNeeded(), |
| MOS_HW_RESOURCE_USAGE_VP_INTERNAL_READ_WRITE_FF)); |
| |
| if (bAllocated) |
| { |
| // initialize Spatial Attributes Configuration Surface |
| VP_PUBLIC_CHK_STATUS_RETURN(InitVeboxSpatialAttributesConfiguration()); |
| } |
| |
| #endif |
| |
| dwSize = GetHistogramSurfaceSize(caps, inputSurface->osSurface->dwWidth, inputSurface->osSurface->dwHeight); |
| |
| VP_PUBLIC_CHK_STATUS_RETURN(m_allocator.ReAllocateSurface( |
| m_veboxRgbHistogram, |
| "VeboxLaceAceRgbHistogram", |
| Format_Buffer, |
| MOS_GFXRES_BUFFER, |
| MOS_TILE_LINEAR, |
| dwSize, |
| 1, |
| false, |
| MOS_MMC_DISABLED, |
| bAllocated, |
| false, |
| IsDeferredResourceDestroyNeeded(), |
| MOS_HW_RESOURCE_USAGE_VP_INTERNAL_WRITE_FF, |
| MOS_TILE_UNSET_GMM, |
| memTypeHistStat, |
| MOS_MEMPOOL_DEVICEMEMORY == memTypeHistStat)); |
| |
| m_isHistogramReallocated = bAllocated; |
| |
| if (bAllocated && NullHW::IsEnabled()) |
| { |
| // Initialize veboxRgbHistogram Surface |
| VP_PUBLIC_CHK_STATUS_RETURN(m_allocator.OsFillResource( |
| &(m_veboxRgbHistogram->osSurface->OsResource), |
| dwSize, |
| InitValue)); |
| } |
| |
| // Allocate Statistics State Surface---------------------------------------- |
| // Width to be a aligned on 64 bytes and height is 1/4 the height |
| // Per frame information written twice per frame for 2 slices |
| // Surface to be a rectangle aligned with dwWidth to get proper dwSize |
| // APG PAth need to make sure input surface width/height is what to processed width/Height |
| uint32_t statistic_size = m_vpPlatformInterface.VeboxQueryStaticSurfaceSize(); |
| dwWidth = MOS_ALIGN_CEIL(inputSurface->osSurface->dwWidth, 64); |
| dwHeight = MOS_ROUNDUP_DIVIDE(inputSurface->osSurface->dwHeight, 4) + |
| MOS_ROUNDUP_DIVIDE(statistic_size * sizeof(uint32_t), dwWidth); |
| dwSize = dwWidth * dwHeight; |
| |
| VP_PUBLIC_CHK_STATUS_RETURN(m_allocator.ReAllocateSurface( |
| m_veboxStatisticsSurface, |
| "VeboxStatisticsSurface", |
| Format_Buffer, |
| MOS_GFXRES_BUFFER, |
| MOS_TILE_LINEAR, |
| dwWidth, |
| dwHeight, |
| false, |
| MOS_MMC_DISABLED, |
| bAllocated, |
| true, |
| IsDeferredResourceDestroyNeeded(), |
| MOS_HW_RESOURCE_USAGE_VP_INTERNAL_WRITE_FF, |
| MOS_TILE_UNSET_GMM, |
| memTypeHistStat, |
| MOS_MEMPOOL_DEVICEMEMORY == memTypeHistStat)); |
| |
| if (bAllocated) |
| { |
| if (MOS_MEMPOOL_DEVICEMEMORY != memTypeHistStat) |
| { |
| // Initialize veboxStatisticsSurface Surface |
| VP_PUBLIC_CHK_STATUS_RETURN(m_allocator.OsFillResource( |
| &(m_veboxStatisticsSurface->osSurface->OsResource), |
| dwSize, |
| InitValue)); |
| m_dwVeboxPerBlockStatisticsWidth = dwWidth; |
| m_dwVeboxPerBlockStatisticsHeight = MOS_ROUNDUP_DIVIDE(inputSurface->osSurface->dwHeight, 4); |
| } |
| } |
| |
| if (caps.bHDR3DLUT) |
| { |
| // HDR |
| dwSize = Get3DLutSize(); |
| VP_PUBLIC_CHK_STATUS_RETURN(m_allocator.ReAllocateSurface( |
| m_vebox3DLookUpTables, |
| "Vebox3DLutTableSurface", |
| Format_Buffer, |
| MOS_GFXRES_BUFFER, |
| MOS_TILE_LINEAR, |
| dwSize, |
| 1, |
| false, |
| MOS_MMC_DISABLED, |
| bAllocated, |
| false, |
| IsDeferredResourceDestroyNeeded())); |
| } |
| // cappipe |
| |
| return MOS_STATUS_SUCCESS; |
| } |
| |
| MOS_STATUS VpResourceManager::AssignSurface(VP_EXECUTE_CAPS caps, VEBOX_SURFACE_ID &surfaceId, SurfaceType surfaceType, VP_SURFACE *inputSurface, VP_SURFACE *outputSurface, VP_SURFACE *pastSurface, VP_SURFACE *futureSurface, VP_SURFACE_GROUP &surfGroup) |
| { |
| VP_FUNC_CALL(); |
| |
| switch (surfaceId) |
| { |
| case VEBOX_SURFACE_INPUT: |
| if (nullptr == inputSurface) |
| { |
| VP_PUBLIC_ASSERTMESSAGE("inputSurface should not be nullptr when surfaceId being VEBOX_SURFACE_INPUT."); |
| break; |
| } |
| surfGroup.insert(std::make_pair(surfaceType, inputSurface)); |
| break; |
| case VEBOX_SURFACE_OUTPUT: |
| if (nullptr == outputSurface) |
| { |
| VP_PUBLIC_ASSERTMESSAGE("outputSurface should not be nullptr when surfaceId being VEBOX_SURFACE_OUTPUT."); |
| break; |
| } |
| surfGroup.insert(std::make_pair(surfaceType, outputSurface)); |
| break; |
| case VEBOX_SURFACE_PAST_REF: |
| if (caps.bDN && m_pastDnOutputValid) |
| { |
| surfGroup.insert(std::make_pair(surfaceType, m_veboxDenoiseOutput[(m_currentDnOutput + 1) & 1])); |
| } |
| else |
| { |
| auto curDnOutputSurface = m_veboxDenoiseOutput[m_currentDnOutput]; |
| |
| if (nullptr == pastSurface) |
| { |
| VP_PUBLIC_ASSERTMESSAGE("pastSurface should not be nullptr when surfaceId being VEBOX_SURFACE_PAST_REF."); |
| break; |
| } |
| |
| if (!caps.bDN || |
| nullptr == curDnOutputSurface || |
| // When MEDIA_IS_SKU(skuTable, FtrMediaTile64) == true, DN output surface must be tile64, |
| // while pastSurface passed by OS maybe tile4, which is different from DN output surface. |
| // For such case, passSurface cannot be used, as vebox previous input surface and vebox |
| // DN output surface must share same setting. The derive pitch in vebox output surface |
| // state is for both of them. Check pitch to handle it. |
| pastSurface->osSurface->dwPitch == curDnOutputSurface->osSurface->dwPitch) |
| { |
| surfGroup.insert(std::make_pair(surfaceType, pastSurface)); |
| } |
| else |
| { |
| // DN case with m_pastDnOutputValid being false. pastSurface cannot be used here as pitch |
| // of pastSurface is different from current DN output surface. |
| VP_PUBLIC_NORMALMESSAGE("Do not use pastSurface. pastSurf (TileModeGmm: %d, pitch: %d) vs curDnOutputSurface (TileModeGmm: %d, pitch: %d)", |
| pastSurface->osSurface->TileModeGMM, |
| pastSurface->osSurface->dwPitch, |
| curDnOutputSurface->osSurface->TileModeGMM, |
| curDnOutputSurface->osSurface->dwPitch); |
| } |
| } |
| break; |
| case VEBOX_SURFACE_FUTURE_REF: |
| if (nullptr == futureSurface) |
| { |
| VP_PUBLIC_ASSERTMESSAGE("futureSurface should not be nullptr when surfaceId being VEBOX_SURFACE_FUTURE_REF."); |
| break; |
| } |
| surfGroup.insert(std::make_pair(surfaceType, futureSurface)); |
| break; |
| case VEBOX_SURFACE_FRAME0: |
| surfGroup.insert(std::make_pair(surfaceType, m_veboxOutput[(m_currentDnOutput + 0) % m_veboxOutputCount])); |
| break; |
| case VEBOX_SURFACE_FRAME1: |
| surfGroup.insert(std::make_pair(surfaceType, m_veboxOutput[(m_currentDnOutput + 1) % m_veboxOutputCount])); |
| break; |
| case VEBOX_SURFACE_FRAME2: |
| surfGroup.insert(std::make_pair(surfaceType, m_veboxOutput[(m_currentDnOutput + 2) % m_veboxOutputCount])); |
| break; |
| case VEBOX_SURFACE_FRAME3: |
| surfGroup.insert(std::make_pair(surfaceType, m_veboxOutput[(m_currentDnOutput + 3) % m_veboxOutputCount])); |
| break; |
| default: |
| break; |
| } |
| return MOS_STATUS_SUCCESS; |
| } |
| |
| MOS_STATUS VpResourceManager::AssignVeboxResource(VP_EXECUTE_CAPS& caps, VP_SURFACE *inputSurface, VP_SURFACE *outputSurface, |
| VP_SURFACE *pastSurface, VP_SURFACE *futureSurface, RESOURCE_ASSIGNMENT_HINT resHint, VP_SURFACE_SETTING &surfSetting) |
| { |
| VP_FUNC_CALL(); |
| VP_PUBLIC_CHK_NULL_RETURN(inputSurface); |
| VP_PUBLIC_CHK_NULL_RETURN(inputSurface->osSurface); |
| VP_PUBLIC_CHK_NULL_RETURN(outputSurface); |
| VP_PUBLIC_CHK_NULL_RETURN(outputSurface->osSurface); |
| |
| MOS_FORMAT format; |
| MOS_TILE_TYPE TileType; |
| uint32_t dwWidth; |
| uint32_t dwHeight; |
| uint32_t dwSize; |
| uint32_t i; |
| auto& surfGroup = surfSetting.surfGroup; |
| |
| // Render case reuse vebox resource, and don`t need re-allocate. |
| if (!caps.bRender || |
| (caps.bRender && caps.bDnKernelUpdate)) |
| { |
| VP_PUBLIC_CHK_STATUS_RETURN(AllocateVeboxResource(caps, inputSurface, outputSurface)); |
| } |
| |
| if (caps.bDI || caps.bDiProcess2ndField) |
| { |
| bool b60fpsDi = resHint.b60fpsDi || caps.bDiProcess2ndField; |
| VEBOX_SURFACES_CONFIG cfg(b60fpsDi, caps.bSFC, m_sameSamples, m_outOfBound, m_currentFrameIds.pastFrameAvailable, |
| m_currentFrameIds.futureFrameAvailable, IsInterleaveFirstField(inputSurface->SampleType)); |
| auto it = m_veboxSurfaceConfigMap.find(cfg.value); |
| if (m_veboxSurfaceConfigMap.end() == it) |
| { |
| VP_PUBLIC_CHK_STATUS_RETURN(MOS_STATUS_INVALID_PARAMETER); |
| } |
| auto surfaces = it->second; |
| VP_PUBLIC_CHK_STATUS_RETURN(AssignSurface(caps, surfaces.currentInputSurface, SurfaceTypeVeboxInput, inputSurface, outputSurface, pastSurface, futureSurface, surfSetting.surfGroup)); |
| VP_PUBLIC_CHK_STATUS_RETURN(AssignSurface(caps, surfaces.pastInputSurface, SurfaceTypeVeboxPreviousInput, inputSurface, outputSurface, pastSurface, futureSurface, surfSetting.surfGroup)); |
| VP_PUBLIC_CHK_STATUS_RETURN(AssignSurface(caps, surfaces.currentOutputSurface, SurfaceTypeVeboxCurrentOutput, inputSurface, outputSurface, pastSurface, futureSurface, surfSetting.surfGroup)); |
| VP_PUBLIC_CHK_STATUS_RETURN(AssignSurface(caps, surfaces.pastOutputSurface, SurfaceTypeVeboxPreviousOutput, inputSurface, outputSurface, pastSurface, futureSurface, surfSetting.surfGroup)); |
| |
| if (caps.bDN) |
| { |
| // Insert DN output surface |
| surfGroup.insert(std::make_pair(SurfaceTypeDNOutput, m_veboxDenoiseOutput[m_currentDnOutput])); |
| } |
| |
| caps.bRefValid = surfGroup.find(SurfaceTypeVeboxPreviousInput) != surfGroup.end(); |
| } |
| else |
| { |
| surfGroup.insert(std::make_pair(SurfaceTypeVeboxInput, inputSurface)); |
| surfGroup.insert(std::make_pair(SurfaceTypeVeboxCurrentOutput, GetVeboxOutputSurface(caps, outputSurface))); |
| |
| if (caps.bDN) |
| { |
| // Insert DN output surface |
| surfGroup.insert(std::make_pair(SurfaceTypeDNOutput, m_veboxDenoiseOutput[m_currentDnOutput])); |
| // Insert DN Reference surface |
| if (caps.bRefValid) |
| { |
| surfGroup.insert(std::make_pair(SurfaceTypeVeboxPreviousInput, m_veboxDenoiseOutput[(m_currentDnOutput + 1) & 1])); |
| } |
| } |
| } |
| |
| if (VeboxSTMMNeeded(caps, true)) |
| { |
| // Insert STMM input surface |
| surfGroup.insert(std::make_pair(SurfaceTypeSTMMIn, m_veboxSTMMSurface[m_currentStmmIndex])); |
| // Insert STMM output surface |
| surfGroup.insert(std::make_pair(SurfaceTypeSTMMOut, m_veboxSTMMSurface[(m_currentStmmIndex + 1) & 1])); |
| } |
| |
| #if VEBOX_AUTO_DENOISE_SUPPORTED |
| // Insert Vebox auto DN noise level surface |
| surfGroup.insert(std::make_pair(SurfaceTypeAutoDNNoiseLevel, m_veboxDNTempSurface)); |
| // Insert Vebox auto DN spatial config surface/buffer |
| surfGroup.insert(std::make_pair(SurfaceTypeAutoDNSpatialConfig, m_veboxDNSpatialConfigSurface)); |
| #endif |
| |
| // Insert Vebox histogram surface |
| surfGroup.insert(std::make_pair(SurfaceTypeLaceAceRGBHistogram, m_veboxRgbHistogram)); |
| |
| // Insert Vebox statistics surface |
| surfGroup.insert(std::make_pair(SurfaceTypeStatistics, m_veboxStatisticsSurface)); |
| surfSetting.dwVeboxPerBlockStatisticsHeight = m_dwVeboxPerBlockStatisticsHeight; |
| surfSetting.dwVeboxPerBlockStatisticsWidth = m_dwVeboxPerBlockStatisticsWidth; |
| |
| if (VeboxHdr3DlutNeeded(caps)) |
| { |
| // Insert Vebox 3Dlut surface |
| surfGroup.insert(std::make_pair(SurfaceType3dLut, m_vebox3DLookUpTables)); |
| } |
| |
| // Update previous Dn output flag for next frame to use. |
| if (surfGroup.find(SurfaceTypeDNOutput) != surfGroup.end() || m_sameSamples && m_pastDnOutputValid) |
| { |
| m_pastDnOutputValid = true; |
| } |
| else |
| { |
| m_pastDnOutputValid = false; |
| } |
| |
| return MOS_STATUS_SUCCESS; |
| } |
| |
| bool VpResourceManager::IsOutputSurfaceNeeded(VP_EXECUTE_CAPS caps) |
| { |
| VP_FUNC_CALL(); |
| |
| // check whether intermedia surface needed to create based on caps |
| if (caps.bDnKernelUpdate || // State Heap as putput, but it was not tracked in resource manager yet |
| caps.bVeboxSecureCopy) // State Heap as putput, but it was not tracked in resource manager yet |
| { |
| return false; |
| } |
| else |
| { |
| return true; |
| } |
| } |
| |
| VP_SURFACE* VpResourceManager::GetVeboxOutputSurface(VP_EXECUTE_CAPS& caps, VP_SURFACE *outputSurface) |
| { |
| VP_FUNC_CALL(); |
| |
| if (caps.bRender) |
| { |
| // Place Holder when enable DI |
| return nullptr; |
| } |
| |
| if (!caps.bSFC) // Vebox output directlly to output surface |
| { |
| // RenderTarget will be assigned in VpVeboxCmdPacket::GetSurface. |
| return outputSurface; |
| } |
| else if (caps.bDI && caps.bVebox) // Vebox DI enable |
| { |
| // Place Holder when enable DI |
| return nullptr; |
| } |
| else if (caps.bIECP) // SFC + IECP enabled, output to internal surface |
| { |
| return m_veboxOutput[m_currentDnOutput]; |
| } |
| else if (caps.bDN) // SFC + DN case |
| { |
| // DN + SFC scenario needs IECP implicitly, which need vebox output surface being assigned. |
| // Use m_currentDnOutput to ensure m_veboxOutput surface paired with DN output surface. |
| return m_veboxOutput[m_currentDnOutput]; |
| } |
| else |
| { |
| // Write to SFC cases, Vebox output is not needed. |
| VP_PUBLIC_NORMALMESSAGE("No need output for Vebox output"); |
| return nullptr; |
| } |
| } |
| |
| MOS_STATUS VpResourceManager::InitVeboxSpatialAttributesConfiguration() |
| { |
| VP_FUNC_CALL(); |
| |
| VP_PUBLIC_CHK_NULL_RETURN(m_veboxDNSpatialConfigSurface); |
| VP_PUBLIC_CHK_NULL_RETURN(m_veboxDNSpatialConfigSurface->osSurface); |
| |
| uint8_t* data = (uint8_t*)& g_cInit_VEBOX_SPATIAL_ATTRIBUTES_CONFIGURATIONS; |
| return m_allocator.Write1DSurface(m_veboxDNSpatialConfigSurface, data, |
| (uint32_t)sizeof(VEBOX_SPATIAL_ATTRIBUTES_CONFIGURATION)); |
| } |
| |
| bool VpResourceManager::VeboxOutputNeeded(VP_EXECUTE_CAPS& caps) |
| { |
| VP_FUNC_CALL(); |
| |
| // If DN and/or Hotpixel are the only functions enabled then the only output is the Denoised Output |
| // and no need vebox output. |
| // For any other vebox features being enabled, vebox output surface is needed. |
| if (caps.bDI || |
| caps.bQueryVariance || |
| caps.bDiProcess2ndField || |
| caps.bIECP || |
| (caps.bDN && caps.bSFC)) // DN + SFC needs IECP implicitly and outputs to DI surface |
| { |
| return true; |
| } |
| else |
| { |
| return false; |
| } |
| } |
| |
| bool VpResourceManager::VeboxDenoiseOutputNeeded(VP_EXECUTE_CAPS& caps) |
| { |
| VP_FUNC_CALL(); |
| |
| return caps.bDN; |
| } |
| |
| bool VpResourceManager::VeboxHdr3DlutNeeded(VP_EXECUTE_CAPS &caps) |
| { |
| VP_FUNC_CALL(); |
| |
| return caps.bHDR3DLUT; |
| } |
| |
| // In some case, STMM should not be destroyed even when not being used by current workload to maintain data, |
| // e.g. DI second field case. |
| // If queryAssignment == true, query whether STMM needed by current workload. |
| // If queryAssignment == false, query whether STMM needed to be allocated. |
| bool VpResourceManager::VeboxSTMMNeeded(VP_EXECUTE_CAPS& caps, bool queryAssignment) |
| { |
| VP_FUNC_CALL(); |
| |
| if (queryAssignment) |
| { |
| return caps.bDI || caps.bDN; |
| } |
| else |
| { |
| return caps.bDI || caps.bDiProcess2ndField || caps.bDN; |
| } |
| } |
| |
| }; |