You’re right! There are some max ops. in between, then the max-feat from the 4 conv. layers are concatenated and fed to the Conv1d.
Input is a batch of PointClouds so a tensor with dim. [numShapesInBatch, 3, numPointsPerShape]
This is the forward code:
def forward(self, x):
        batch_size = x.size(0)
        x = get_graph_feature(x, k=self.k)  # (batch_size, 3, num_points) => (batch_size, 3*2, num_points, k)
        x = self.conv1(x)  # (batch_size, 3*2, num_points, k) => (batch_size, 64, num_points, k)
        x1 = x.max(dim=-1, keepdim=False)[0]  # (batch_size, 64, num_points, k) => (batch_size, 64, num_points)

        x = get_graph_feature(x1, k=self.k)
        x = self.conv2(x)
        x2 = x.max(dim=-1, keepdim=False)[0]  # => (batch_size, 64, num_points)

        x = get_graph_feature(x2, k=self.k)
        x = self.conv3(x)
        x3 = x.max(dim=-1, keepdim=False)[0]  # => (batch_size, 128, num_points)

        x = get_graph_feature(x3, k=self.k)
        x = self.conv4(x)
        x4 = x.max(dim=-1, keepdim=False)[0]  # => (batch_size, 256, num_points)

        x = torch.cat((x1, x2, x3, x4), dim=1)  # => (batch_size, 64+64+128+256, num_points)

        x = self.conv5(x)  #(batch_size, 64+64+128+256, num_points) => (batch_size, emb_dims, num_points)
        x1 = F.adaptive_max_pool1d(x, 1).view(batch_size, -1)
        x2 = F.adaptive_avg_pool1d(x, 1).view(batch_size, -1)
        x = torch.cat((x1, x2), 1)

        # Classification Forward
        x = self.cls(x)
        return x

(P.S. the code is from https://github.com/WangYueFt/dgcnn/blob/20fdb459ca5d10fe8aba1d296e66340f65990b85/pytorch/model.py#L88 2 )