Example #1
0
 public DrawIndexedAttribs opaqueDrawAttribs(GpuValueType indexType)
 {
     return(new DrawIndexedAttribs(false)
     {
         NumIndices = drawInfo.opaqueIndices,
         IndexType = indexType,
         Flags = DrawFlags.VerifyAll,
         FirstIndexLocation = drawInfo.firstOpaqueIndex
     });
 }
Example #2
0
 public DrawIndexedAttribs transparentDrawAttribs(GpuValueType indexType)
 {
     return(new DrawIndexedAttribs(false)
     {
         NumIndices = drawInfo.transparentIndices,
         IndexType = indexType,
         Flags = DrawFlags.VerifyAll,
         FirstIndexLocation = drawInfo.firstTransparentIndex
     });
 }
Example #3
0
 internal IndexedMesh(IBuffer vb, IBuffer ib, int countIndices, GpuValueType indexType, BoundingBox?bbox = null)
 {
     vertexBuffer        = vb;
     indexBuffer         = ib;
     drawCall            = new DrawIndexedAttribs(true);
     drawCall.NumIndices = countIndices;
     drawCall.IndexType  = indexType;
     drawCall.Flags      = DrawFlags.VerifyAll;
     boundingBox         = bbox;
 }
Example #4
0
        public void flush()
        {
            tesselatorThread.syncThreads();

            // The commented out code doesn't work.
            // Might be a bug in the native code which results in false positive eClipResult.FillsEntireViewport result.
            // Spent couple hours trying to debug but failed, then disabled the optimization.

            /* int topmostFillingCmd = 0;
             * for( int i = calls.length - 1; i >= 0; i-- )
             * {
             *      ref sDrawCall dc = ref calls[ i ];
             *      if( dc.order.sn < 0 )
             *              continue;
             *      ref sPendingDrawCall pdc = ref drawMeshes.meshes[ dc.order.sn ];
             *      eRenderPassFlags rpf = pdc.mesh.drawInfo.renderPassFlags;
             *      passFlags |= rpf;
             *
             *      eClipResult clipResult = pdc.mesh.clipResult;
             *      if( clipResult != eClipResult.FillsEntireViewport )
             *              continue;
             *      if( rpf != eRenderPassFlags.Opaque )
             *              continue;
             *      if( !pdc.mesh.sourcePath.flags.HasFlag( ePathFlags.AnyFilledFigures ) )
             *              continue;
             *
             *      // Detected an opaque mesh that fills entire clip area. Discarding all draw commands before that.
             *      ConsoleLogger.logDebug( "Commands [ 0 - {0} ] are occluded, only rendering [ {1} - {2} ]", i - 1, i, calls.length - 1 );
             *      topmostFillingCmd = i;
             *      break;
             * }
             * Span<sDrawCall> drawCallsSpan = calls.read().Slice( topmostFillingCmd ); */

            Span <sDrawCall> drawCallsSpan = calls.read();

            drawMeshes.summarize(ref passFlags, out eShaderMacros drawFeatures);
            if (passFlags == eRenderPassFlags.None)
            {
                return;
            }

            updatePalette();
            if (drawFeatures.HasFlag(eShaderMacros.TextRendering))
            {
                updateFontTextures();
            }

            // Vertex/index buffers are concatenated and shared across the two passes.
            // The trade off here is "very rarely save few kb of bandwidth with 16 bit indices" versus "always save map/unmap interop calls and kernel calls"
            // Also, this slightly simplifies command lists implementation.
            layoutBuffers(drawCallsSpan);

            var ic = resources.context.context;

            uploadVertices(ic, drawCallsSpan);
            ic.setVertexBuffer(resources.vertexBuffer);

            GpuValueType indexType = uploadIndices(ic, drawCallsSpan);

            ic.SetIndexBuffer(resources.indexBuffer, 0);

            bool anyOpaqueMeshes = false;

            if (buffersLayout.drawInfo.opaqueIndices > 0)
            {
                VrmacStateBase state = states.getState(drawCallsSpan.Length, true, drawFeatures);
                state.uploadDrawCalls(ic, drawCallsSpan, depthValues, ref drawMeshes);
                state.bind(ic);
                DrawIndexedAttribs opaqueCall = buffersLayout.opaqueDrawAttribs(indexType);
                ic.DrawIndexed(ref opaqueCall);
                anyOpaqueMeshes = true;
            }

            if (buffersLayout.drawInfo.transparentIndices > 0)
            {
                VrmacStateBase state = states.getState(drawCallsSpan.Length, false, drawFeatures);
                // The draw calls buffer is the same. Only uploading here if there were no opaque meshes.
                // The reason we can't do that in advance outside these if-s - different GPU states upload to different locations.
                if (!anyOpaqueMeshes)
                {
                    state.uploadDrawCalls(ic, drawCallsSpan, depthValues, ref drawMeshes);
                }

                state.bind(ic);
                DrawIndexedAttribs transparentCall = buffersLayout.transparentDrawAttribs(indexType);
                ic.DrawIndexed(ref transparentCall);
            }

            // Clear everything, but keep the Z
            int z = currentZ;

            begin();
            currentZ = z;
        }