diff --git a/source/Lib/CommonLib/Picture.cpp b/source/Lib/CommonLib/Picture.cpp
index 7ddff73e578b12ec49726ccbedbf3140cad96d46..8d05d1087dc164df5f93f59b9f73e3c71f8c885b 100644
--- a/source/Lib/CommonLib/Picture.cpp
+++ b/source/Lib/CommonLib/Picture.cpp
@@ -193,7 +193,9 @@ Picture::Picture()
   m_spliceIdx = NULL;
   m_ctuNums = 0;
   layerId = NOT_VALID;
+#if !JVET_S0258_SUBPIC_CONSTRAINTS
   numSubpics = 1;
+#endif
   numSlices = 1;
 }
 
diff --git a/source/Lib/CommonLib/Picture.h b/source/Lib/CommonLib/Picture.h
index ee32fa54c7e92bbf22900e2a32caea5bcedeb748..7e9e44ffaece023e7bc78077b83b58d8d6de9de4 100644
--- a/source/Lib/CommonLib/Picture.h
+++ b/source/Lib/CommonLib/Picture.h
@@ -216,12 +216,17 @@ public:
   int  poc;
   uint32_t temporalId;
   int      layerId;
+#if JVET_S0258_SUBPIC_CONSTRAINTS
+  std::vector<SubPic> subPictures;
+  int numSlices;
+#else
   int  numSubpics;
   std::vector<int> subpicWidthInCTUs;
   std::vector<int> subpicHeightInCTUs;
   std::vector<int> subpicCtuTopLeftX;
   std::vector<int> subpicCtuTopLeftY;
   int numSlices;
+#endif
   std::vector<int> sliceSubpicIdx;
 
   bool subLayerNonReferencePictureDueToSTSA;
@@ -232,7 +237,9 @@ public:
   std::vector<bool> m_lossylosslessSliceArray;
   bool interLayerRefPicFlag;
 
+#if !JVET_S0258_SUBPIC_CONSTRAINTS
   std::vector<int> subPicIDs;
+#endif
 
 #if ENABLE_SPLIT_PARALLELISM
   PelStorage m_bufs[PARL_SPLIT_MAX_NUM_JOBS][NUM_PIC_TYPES];
diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h
index 8ca78240a83105d14bb99a6a768fa90ef0324fc7..2be17962bac5651ca634e38c05d80c0b195b609b 100644
--- a/source/Lib/CommonLib/TypeDef.h
+++ b/source/Lib/CommonLib/TypeDef.h
@@ -59,6 +59,8 @@
 
 #define JVET_S0049_ASPECT4                                1 // JVET-S0049 aspect 4: Constrain the value of pps_alf_info_in_ph_flag to be equal to 0 when the PH is in the SH
 
+#define JVET_S0258_SUBPIC_CONSTRAINTS                     1 // JVET-S0258: sub-picture constraints
+
 #define JVET_S0074_SPS_REORDER                            1 // JVET-S0074: aspect 1, rearrange some syntax elements in SPS
 
 #define JVET_S0234_ACT_CRS_FIX                            1 // JVET-S0234: perform chroma residual scaling in RGB domain when ACT is on
diff --git a/source/Lib/CommonLib/UnitTools.cpp b/source/Lib/CommonLib/UnitTools.cpp
index d77cea079700ba9873e40824ba0b831c4e7bba9a..8e11c1ec0e08881003b7b96e28c32a8e24e012b5 100644
--- a/source/Lib/CommonLib/UnitTools.cpp
+++ b/source/Lib/CommonLib/UnitTools.cpp
@@ -155,18 +155,46 @@ bool CU::getRprScaling( const SPS* sps, const PPS* curPPS, Picture* refPic, int&
 
 void CU::checkConformanceILRP(Slice *slice)
 {
-  const int numRefList = (slice->getSliceType() == B_SLICE) ? (2) : (1);
+  const int numRefList = slice->isInterB() ? 2 : 1;
+
+#if JVET_S0258_SUBPIC_CONSTRAINTS
+  int currentSubPicIdx = NOT_VALID;
+
+  // derive sub-picture index for the current slice
+  for( int subPicIdx = 0; subPicIdx < slice->getPic()->cs->sps->getNumSubPics(); subPicIdx++ )
+  {
+    if( slice->getPic()->cs->pps->getSubPic( subPicIdx ).getSubPicID() == slice->getSliceSubPicId() )
+    {
+      currentSubPicIdx = subPicIdx;
+      break;
+    }
+  }
+
+  CHECK( currentSubPicIdx == NOT_VALID, "Sub-picture was not found" );
+
+  if( !slice->getPic()->cs->sps->getSubPicTreatedAsPicFlag( currentSubPicIdx ) )
+  {
+    return;
+  }
+#endif
 
   //constraint 1: The picture referred to by each active entry in RefPicList[ 0 ] or RefPicList[ 1 ] has the same subpicture layout as the current picture 
   bool isAllRefSameSubpicLayout = true;
   for (int refList = 0; refList < numRefList; refList++) // loop over l0 and l1
   {
     RefPicList  eRefPicList = (refList ? REF_PIC_LIST_1 : REF_PIC_LIST_0);
+
     for (int refIdx = 0; refIdx < slice->getNumRefIdx(eRefPicList); refIdx++)
     {
+#if JVET_S0258_SUBPIC_CONSTRAINTS
+      const Picture* refPic = slice->getRefPic( eRefPicList, refIdx );
+
+      if( refPic->subPictures.size() != slice->getPic()->cs->pps->getNumSubPics() )
+#else
       const Picture* refPic = slice->getRefPic(eRefPicList, refIdx)->unscaledPic;
 
       if (refPic->numSubpics != slice->getPic()->cs->pps->getNumSubPics())
+#endif
       {
         isAllRefSameSubpicLayout = false;
         refList = numRefList;
@@ -174,12 +202,26 @@ void CU::checkConformanceILRP(Slice *slice)
       }
       else
       {
+#if JVET_S0258_SUBPIC_CONSTRAINTS
+        for( int i = 0; i < refPic->subPictures.size(); i++ )
+        {
+          const SubPic& refSubPic = refPic->subPictures[i];
+          const SubPic& curSubPic = slice->getPic()->cs->pps->getSubPic( i );
+
+          if( refSubPic.getSubPicWidthInCTUs() != curSubPic.getSubPicWidthInCTUs()
+            || refSubPic.getSubPicHeightInCTUs() != curSubPic.getSubPicHeightInCTUs()
+            || refSubPic.getSubPicCtuTopLeftX() != curSubPic.getSubPicCtuTopLeftX()
+            || refSubPic.getSubPicCtuTopLeftY() != curSubPic.getSubPicCtuTopLeftY()
+            || ( refPic->layerId != slice->getPic()->layerId && refSubPic.getSubPicID() != curSubPic.getSubPicID() )
+            || refSubPic.getTreatedAsPicFlag() != curSubPic.getTreatedAsPicFlag())
+#else
         for (int i = 0; i < refPic->numSubpics; i++)
         {
           if (refPic->subpicWidthInCTUs[i] != slice->getPic()->cs->pps->getSubPic(i).getSubPicWidthInCTUs()
             || refPic->subpicHeightInCTUs[i] != slice->getPic()->cs->pps->getSubPic(i).getSubPicHeightInCTUs()
             || refPic->subpicCtuTopLeftX[i] != slice->getPic()->cs->pps->getSubPic(i).getSubPicCtuTopLeftX()
             || refPic->subpicCtuTopLeftY[i] != slice->getPic()->cs->pps->getSubPic(i).getSubPicCtuTopLeftY())
+#endif
           {
             isAllRefSameSubpicLayout = false;
             refIdx = slice->getNumRefIdx(eRefPicList);
@@ -187,6 +229,14 @@ void CU::checkConformanceILRP(Slice *slice)
             break;
           }
         }
+
+#if JVET_S0258_SUBPIC_CONSTRAINTS
+        // A picture with different sub-picture ID of the collocated sub-picture cannot be used as an active reference picture in the same layer
+        if( refPic->layerId == slice->getPic()->layerId )
+        {
+          isAllRefSameSubpicLayout = isAllRefSameSubpicLayout && refPic->subPictures[currentSubPicIdx].getSubPicID() == slice->getSliceSubPicId();
+        }
+#endif
       }
     }
   }
@@ -199,8 +249,13 @@ void CU::checkConformanceILRP(Slice *slice)
       RefPicList  eRefPicList = (refList ? REF_PIC_LIST_1 : REF_PIC_LIST_0);
       for (int refIdx = 0; refIdx < slice->getNumRefIdx(eRefPicList); refIdx++)
       {
+#if JVET_S0258_SUBPIC_CONSTRAINTS
+        const Picture* refPic = slice->getRefPic( eRefPicList, refIdx );
+        CHECK( refPic->layerId == slice->getPic()->layerId || refPic->subPictures.size() > 1, "The inter-layer reference shall contain a single subpicture or have same subpicture layout with the current picture" );
+#else
         const Picture* refPic = slice->getRefPic(eRefPicList, refIdx)->unscaledPic;
         CHECK(!(refPic->layerId != slice->getPic()->layerId && refPic->numSubpics == 1), "The inter-layer reference shall contain a single subpicture or have same subpicture layout with the current picture");
+#endif
       }
     }
   }
diff --git a/source/Lib/DecoderLib/DecLib.cpp b/source/Lib/DecoderLib/DecLib.cpp
index a94f901e0a2c76de844c3ce02af696bc9fc55ecc..e02bc98bade5df02c58960aa49f4a97afe5f2072 100644
--- a/source/Lib/DecoderLib/DecLib.cpp
+++ b/source/Lib/DecoderLib/DecLib.cpp
@@ -2223,6 +2223,14 @@ bool DecLib::xDecodeSlice(InputNALUnit &nalu, int &iSkipFrame, int iPOCLastDispl
     checkPicTypeAfterEos();
 #endif
     // store sub-picture numbers, sizes, and locations with a picture
+#if JVET_S0258_SUBPIC_CONSTRAINTS
+    pcSlice->getPic()->subPictures.clear();
+
+    for( int subPicIdx = 0; subPicIdx < sps->getNumSubPics(); subPicIdx++ )
+    {
+      pcSlice->getPic()->subPictures.push_back( pps->getSubPic( subPicIdx ) );
+    }
+#else
     pcSlice->getPic()->numSubpics = sps->getNumSubPics();
     pcSlice->getPic()->subpicWidthInCTUs.clear();
     pcSlice->getPic()->subpicHeightInCTUs.clear();
@@ -2235,6 +2243,7 @@ bool DecLib::xDecodeSlice(InputNALUnit &nalu, int &iSkipFrame, int iPOCLastDispl
       pcSlice->getPic()->subpicCtuTopLeftX.push_back(pps->getSubPic(subPicIdx).getSubPicCtuTopLeftX());
       pcSlice->getPic()->subpicCtuTopLeftY.push_back(pps->getSubPic(subPicIdx).getSubPicCtuTopLeftY());
     }
+#endif
     pcSlice->getPic()->numSlices = pps->getNumSlicesInPic();
     pcSlice->getPic()->sliceSubpicIdx.clear();
   }
@@ -2255,6 +2264,7 @@ bool DecLib::xDecodeSlice(InputNALUnit &nalu, int &iSkipFrame, int iPOCLastDispl
 
   pcSlice->scaleRefPicList( scaledRefPic, m_pcPic->cs->picHeader, m_parameterSetManager.getAPSs(), m_picHeader.getLmcsAPS(), m_picHeader.getScalingListAPS(), true );
 
+#if !JVET_S0258_SUBPIC_CONSTRAINTS
   // For each value of i in the range of 0 to sps_num_subpics_minus1, inclusive, when the value of SubpicIdVal[ i ] of a current picture is not equal to the value of SubpicIdVal[ i ] of a reference picture,
   // the active entries of the RPLs of the coded slices in the i-th subpicture of the current picture shall not include that reference picture.
 
@@ -2301,6 +2311,7 @@ bool DecLib::xDecodeSlice(InputNALUnit &nalu, int &iSkipFrame, int iPOCLastDispl
       }
     }
   }
+#endif
 
     if (!pcSlice->isIntra())
     {
diff --git a/source/Lib/DecoderLib/DecSlice.cpp b/source/Lib/DecoderLib/DecSlice.cpp
index f70fb73f55aaebae628dc795a19ed9f1daff5ef2..ed1b390a9a11f97ddbce1195a4803c81e77a236e 100644
--- a/source/Lib/DecoderLib/DecSlice.cpp
+++ b/source/Lib/DecoderLib/DecSlice.cpp
@@ -127,7 +127,11 @@ void DecSlice::decompressSlice( Slice* slice, InputBitstream* bitstream, int deb
   DTRACE( g_trace_ctx, D_HEADER, "=========== POC: %d ===========\n", slice->getPOC() );
 
 
+#if JVET_S0258_SUBPIC_CONSTRAINTS
+  if( slice->getSliceType() != I_SLICE && slice->getRefPic( REF_PIC_LIST_0, 0 )->subPictures.size() > 1 )
+#else
   if (slice->getSliceType() != I_SLICE && slice->getRefPic(REF_PIC_LIST_0, 0)->numSubpics > 1)
+#endif
   {
     clipMv = clipMvInSubpic;
   }
@@ -166,7 +170,12 @@ void DecSlice::decompressSlice( Slice* slice, InputBitstream* bitstream, int deb
         for (int idx = 0; idx < n; idx++)
         {
           Picture *refPic = slice->getRefPic((RefPicList)rlist, idx);
+
+#if JVET_S0258_SUBPIC_CONSTRAINTS
+          if( !refPic->getSubPicSaved() && refPic->subPictures.size() > 1 )
+#else
           if (!refPic->getSubPicSaved() && refPic->numSubpics > 1)
+#endif
           {
             refPic->saveSubPicBorder(refPic->getPOC(), subPicX, subPicY, subPicWidth, subPicHeight);
             refPic->extendSubPicBorder(refPic->getPOC(), subPicX, subPicY, subPicWidth, subPicHeight);
diff --git a/source/Lib/EncoderLib/EncGOP.cpp b/source/Lib/EncoderLib/EncGOP.cpp
index b4b2044981a358d33d06b42ad417d1b877244e2e..16d9fbf88a949ff697056d4351693ae1d2fdbc04 100644
--- a/source/Lib/EncoderLib/EncGOP.cpp
+++ b/source/Lib/EncoderLib/EncGOP.cpp
@@ -2265,6 +2265,14 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic,
     pcSlice->constructRefPicList(rcListPic);
 
     // store sub-picture numbers, sizes, and locations with a picture
+#if JVET_S0258_SUBPIC_CONSTRAINTS
+    pcSlice->getPic()->subPictures.clear();
+
+    for( int subPicIdx = 0; subPicIdx < pcPic->cs->pps->getNumSubPics(); subPicIdx++ )
+    {
+      pcSlice->getPic()->subPictures.push_back( pcPic->cs->pps->getSubPic( subPicIdx ) );
+    }
+#else
     pcSlice->getPic()->numSubpics = pcPic->cs->pps->getNumSubPics();
     pcSlice->getPic()->subpicWidthInCTUs.clear();
     pcSlice->getPic()->subpicHeightInCTUs.clear();
@@ -2277,6 +2285,7 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic,
       pcSlice->getPic()->subpicCtuTopLeftX.push_back(pcPic->cs->pps->getSubPic(subPicIdx).getSubPicCtuTopLeftX());
       pcSlice->getPic()->subpicCtuTopLeftY.push_back(pcPic->cs->pps->getSubPic(subPicIdx).getSubPicCtuTopLeftY());
     }
+#endif
 
     const VPS* vps = pcPic->cs->vps;
     int layerIdx = vps == nullptr ? 0 : vps->getGeneralLayerIdx(pcPic->layerId);
@@ -2801,7 +2810,11 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic,
         }
         m_pcSliceEncoder->setLosslessSlice(pcPic, isLossless);
 
+#if JVET_S0258_SUBPIC_CONSTRAINTS
+        if( pcSlice->getSliceType() != I_SLICE && pcSlice->getRefPic( REF_PIC_LIST_0, 0 )->subPictures.size() > 1 )
+#else
         if (pcSlice->getSliceType() != I_SLICE && pcSlice->getRefPic(REF_PIC_LIST_0, 0)->numSubpics > 1)
+#endif
         {
           clipMv = clipMvInSubpic;
           m_pcEncLib->getInterSearch()->setClipMvInSubPic(true);
diff --git a/source/Lib/EncoderLib/EncSlice.cpp b/source/Lib/EncoderLib/EncSlice.cpp
index 8897f7e5e4b92565362ff59109e63325c0f083d8..0d71f608f7ede97f16d91eaaf70d7dc9e7890254 100644
--- a/source/Lib/EncoderLib/EncSlice.cpp
+++ b/source/Lib/EncoderLib/EncSlice.cpp
@@ -1553,7 +1553,12 @@ void EncSlice::encodeCtus( Picture* pcPic, const bool bCompressEntireSlice, cons
         for (int idx = 0; idx < n; idx++)
         {
           Picture *refPic = pcSlice->getRefPic((RefPicList)rlist, idx);
+
+#if JVET_S0258_SUBPIC_CONSTRAINTS
+          if( !refPic->getSubPicSaved() && refPic->subPictures.size() > 1 )
+#else
           if (!refPic->getSubPicSaved() && refPic->numSubpics > 1)
+#endif
           {
             refPic->saveSubPicBorder(refPic->getPOC(), subPicX, subPicY, subPicWidth, subPicHeight);
             refPic->extendSubPicBorder(refPic->getPOC(), subPicX, subPicY, subPicWidth, subPicHeight);