예제 #1
0
        public static unsafe RenderCommand SetShaderTextureSamplers(Shader shader, FastClearList <KVP <TextureSamplerBinding, TextureSampler> > values)
        {
            Assure.NotNull(shader);
            Assure.False(shader.IsDisposed, "Shader was disposed.");
            Assure.NotNull(values);
            IntPtr *resourceHandleArrayPtr = (IntPtr *)AllocAndZeroTemp(shader.NumTextureSamplerSlots * (uint)sizeof(IntPtr));

            for (int i = 0; i < values.Count; ++i)
            {
                var kvp = values[i];
                if (kvp.Value == null)
                {
                    continue;                                    // Legitimate: If we want to set a bind to null, this is how it's done
                }
                resourceHandleArrayPtr[kvp.Key.SlotIndex] = (IntPtr)kvp.Value.ResourceHandle;
            }
            return(new RenderCommand(shader.SetTextureSamplersInstruction, (IntPtr)resourceHandleArrayPtr, shader.NumTextureSamplerSlots, 0U));
        }
예제 #2
0
        internal virtual void RCQUpdateResources(RenderCommandQueue commandQueue, ShaderResourcePackage shaderResources)
        {
            for (int i = 0; i < ConstantBufferBindings.Length; i++)
            {
                commandQueue.QueueCommand(RenderCommand.DiscardWriteShaderConstantBuffer(
                                              ConstantBufferBindings[i], shaderResources.GetValue(ConstantBufferBindings[i])
                                              ));
            }

            if (TextureSamplerBindings.Length > 0)
            {
                if (texSamplerValueDict == null)
                {
                    texSamplerValueDict = new FastClearList <KVP <TextureSamplerBinding, TextureSampler> >();
                }
                texSamplerValueDict.Clear();
                for (int i = 0; i < TextureSamplerBindings.Length; ++i)
                {
                    var tsb = TextureSamplerBindings[i];
                    texSamplerValueDict.Add(new KVP <TextureSamplerBinding, TextureSampler>(tsb, shaderResources.GetValue(tsb)));
                }
                commandQueue.QueueCommand(RenderCommand.SetShaderTextureSamplers(this, texSamplerValueDict));
            }

            if (ResourceViewBindings.Length > 0)
            {
                if (resViewValueDict == null)
                {
                    resViewValueDict = new FastClearList <KVP <ResourceViewBinding, IResourceView> >();
                }
                resViewValueDict.Clear();
                for (int i = 0; i < ResourceViewBindings.Length; ++i)
                {
                    var rvb = ResourceViewBindings[i];
                    resViewValueDict.Add(new KVP <ResourceViewBinding, IResourceView>(rvb, shaderResources.GetValue(rvb)));
                    Assure.False(
                        ((BaseResourceView)shaderResources.GetValue(ResourceViewBindings[i])) != null &&
                        ((BaseResourceView)shaderResources.GetValue(ResourceViewBindings[i])).Resource.PermittedBindings == GPUBindings.None,
                        "Underlying resource has no permitted GPU bindings."
                        );
                }
                commandQueue.QueueCommand(RenderCommand.SetShaderResourceViews(this, resViewValueDict));
            }
        }
예제 #3
0
        internal virtual void RCQUpdateResources(RenderCommandQueue commandQueue)
        {
            for (int i = 0; i < ConstantBufferBindings.Length; i++)
            {
                commandQueue.QueueCommand(RenderCommand.DiscardWriteShaderConstantBuffer(
                                              ConstantBufferBindings[i], ConstantBufferBindings[i].CurValuePtr
                                              ));
            }

            if (TextureSamplerBindings.Length > 0)
            {
                if (texSamplerValueDict == null)
                {
                    texSamplerValueDict = new FastClearList <KVP <TextureSamplerBinding, TextureSampler> >();
                }
                texSamplerValueDict.Clear();
                for (int i = 0; i < TextureSamplerBindings.Length; ++i)
                {
                    texSamplerValueDict.Add(new KVP <TextureSamplerBinding, TextureSampler>(TextureSamplerBindings[i], TextureSamplerBindings[i].GetBoundResource()));
                }
                commandQueue.QueueCommand(RenderCommand.SetShaderTextureSamplers(this, texSamplerValueDict));
            }

            if (ResourceViewBindings.Length > 0)
            {
                if (resViewValueDict == null)
                {
                    resViewValueDict = new FastClearList <KVP <ResourceViewBinding, IResourceView> >();
                }
                resViewValueDict.Clear();
                for (int i = 0; i < ResourceViewBindings.Length; ++i)
                {
                    resViewValueDict.Add(new KVP <ResourceViewBinding, IResourceView>(ResourceViewBindings[i], ResourceViewBindings[i].GetBoundResourceAsBaseResourceView()));
                    Assure.False(ResourceViewBindings[i].GetBoundResourceAsBaseResourceView().Resource.PermittedBindings == GPUBindings.None, "Underlying resource has no permitted GPU bindings.");
                }
                commandQueue.QueueCommand(RenderCommand.SetShaderResourceViews(this, resViewValueDict));
            }
        }
        private void RenderCache_IterateMaterial(int materialIndex)
        {
            // Set up context variables
            KeyValuePair <Material, ModelInstanceManager.MIDArray> currentKVP = currentInstanceData[materialIndex];
            Material currentMaterial = currentKVP.Key;

            ModelInstanceManager.MIDArray currentMID = currentKVP.Value;

            // Skip this material if it or its shader are disposed
            if (currentMaterial.IsDisposed || currentMaterial.Shader.IsDisposed)
            {
                return;
            }

            // Skip this material if we're not using it
            bool inUse = false;

            for (int i = 0; i < currentMID.Length; ++i)
            {
                if (currentMID.Data[i].InUse)
                {
                    inUse = true;
                    break;
                }
            }
            if (!inUse)
            {
                return;
            }

            // Prepare shader according to material params, and switch to it or update it
            if (lastSetFragmentShader != currentMaterial.Shader || lastFrameNum != frameNum)
            {
                lastSetFragmentShader = currentMaterial.Shader;
                lastFrameNum          = frameNum;
                QueueShaderSwitch(lastSetFragmentShader);
            }
            var queuedSRP = currentMaterial.FragmentShaderResourcePackage;

            if (lastSetFragmentShader == geomFSWithShadowSupport)
            {
                if (modifiedSRP == null)
                {
                    modifiedSRP = new ShaderResourcePackage();
                }
                modifiedSRP.CopyFrom(queuedSRP);
                modifiedSRP.SetValue((ResourceViewBinding)lastSetFragmentShader.GetBindingByIdentifier("ShadowMap"), previousShadowBufferSRV);
                queuedSRP = modifiedSRP;
            }
            QueueShaderResourceUpdate(lastSetFragmentShader, queuedSRP);

            // Filter & sort
            if (materialFilteringWorkspace == null || materialFilteringWorkspace.Length < currentCache.NumModels)
            {
                materialFilteringWorkspace = new FastClearList <Transform> [currentCache.NumModels];
                for (int i = 0; i < materialFilteringWorkspace.Length; ++i)
                {
                    materialFilteringWorkspace[i] = new FastClearList <Transform>();
                }
            }
            for (int i = 0; i < materialFilteringWorkspace.Length; ++i)
            {
                materialFilteringWorkspace[i].Clear();
            }

            SortByProximityToCamera(currentMID);
            uint numInstances = 0U;

            for (uint i = 0U; i < currentMID.Length; ++i)
            {
                ModelInstanceData curMID = sortedModelData[i];
                if (!curMID.InUse)
                {
                    continue;
                }
                SceneLayer layer = currentSceneLayers[curMID.SceneLayerIndex];
                if (layer == null || !layer.GetRenderingEnabled() || !addedSceneLayers.Contains(layer))
                {
                    continue;
                }

                if (curMID.ModelIndex == __VEGG_MH.ModelIndex && currentCache.ID == __VEGG_MH.GeoCacheID)
                {
                    int instanceIndex = 0;
                    for (int j = 0; j < currentMID.Length; ++j)
                    {
                        if (currentMID.Data[j].Transform == curMID.Transform)
                        {
                            instanceIndex = j;
                            break;
                        }
                    }
                    Quaternion rot = Quaternion.IDENTITY;
                    foreach (var kvp in __VEGG_MIH_ARR)
                    {
                        if (kvp.Key.InstanceIndex == instanceIndex)
                        {
                            rot = kvp.Value;
                            break;
                        }
                    }
                    materialFilteringWorkspace[curMID.ModelIndex].Add(curMID.Transform.RotateBy(rot));
                }
                else
                {
                    materialFilteringWorkspace[curMID.ModelIndex].Add(curMID.Transform);
                }
                ++numInstances;
            }

            // Concatenate & queue render commands
            if (instanceConcatWorkspace == null || instanceConcatWorkspace.Length < numInstances)
            {
                instanceConcatWorkspace = new Matrix[numInstances << 1];                 // x2 so we don't create loads of garbage if the count keeps increasing by 1
            }

            uint instanceStartOffset = RenderCache_IterateMaterial_ConcatReserve(numInstances);
            uint nextWorkspaceIndex = 0;
            uint outVBStartIndex, outIBStartIndex, outVBCount, outIBCount;

            for (uint mI = 0U; mI < materialFilteringWorkspace.Length; ++mI)
            {
                FastClearList <Transform> filteredTransformList = materialFilteringWorkspace[mI];
                int numFilteredTransforms = filteredTransformList.Count;
                if (numFilteredTransforms == 0)
                {
                    continue;
                }

                currentCache.GetModelBufferValues(mI, out outVBStartIndex, out outIBStartIndex, out outVBCount, out outIBCount);

                QueueRenderCommand(RenderCommand.DrawIndexedInstanced(
                                       (int)outVBStartIndex,
                                       outIBStartIndex,
                                       outIBCount,
                                       nextWorkspaceIndex + instanceStartOffset,
                                       (uint)numFilteredTransforms
                                       ));

                for (int iI = 0; iI < numFilteredTransforms; ++iI)
                {
                    if (mI == __EGGHACK_MH.ModelIndex && currentCache.ID == __EGGHACK_MH.GeoCacheID)
                    {
                        instanceConcatWorkspace[nextWorkspaceIndex++] = filteredTransformList[iI].RotateBy(__EGGHACK_ROT).AsMatrixTransposed;
                    }
                    else
                    {
                        instanceConcatWorkspace[nextWorkspaceIndex++] = filteredTransformList[iI].AsMatrixTransposed;
                    }
                }
            }

            RenderCache_IterateMaterial_Concat(instanceConcatWorkspace, instanceStartOffset, numInstances);
        }
예제 #5
0
        private void RenderCache_IterateMaterial(int materialIndex)
        {
            // Set up context variables
            KeyValuePair <Material, ModelInstanceManager.MIDArray> currentKVP = currentInstanceData[materialIndex];
            Material currentMaterial = currentKVP.Key;

            ModelInstanceManager.MIDArray currentMID = currentKVP.Value;

            // Skip this material if it or its shader are disposed
            if (currentMaterial.IsDisposed || currentMaterial.Shader.IsDisposed)
            {
                return;
            }

            // Prepare shader according to material params, and switch to it or update it
            if (lastSetFragmentShader != currentMaterial.Shader || lastFrameNum != frameNum)
            {
                lastSetFragmentShader = currentMaterial.Shader;
                lastFrameNum          = frameNum;
                QueueShaderSwitch(lastSetFragmentShader);
            }
            QueueShaderResourceUpdate(lastSetFragmentShader, currentMaterial.FragmentShaderResourcePackage);


            // Filter & sort
            if (materialFilteringWorkspace == null || materialFilteringWorkspace.Length < currentCache.NumModels)
            {
                materialFilteringWorkspace = new FastClearList <Transform> [currentCache.NumModels];
                for (int i = 0; i < materialFilteringWorkspace.Length; ++i)
                {
                    materialFilteringWorkspace[i] = new FastClearList <Transform>();
                }
            }
            for (int i = 0; i < materialFilteringWorkspace.Length; ++i)
            {
                materialFilteringWorkspace[i].Clear();
            }

            ModelInstanceData *midData = currentMID.Data;
            uint numInstances          = 0U;

            for (uint i = 0U; i < currentMID.Length; ++i)
            {
                ModelInstanceData curMID = midData[i];
                if (!curMID.InUse)
                {
                    continue;
                }
                SceneLayer layer = currentSceneLayers[curMID.SceneLayerIndex];
                if (layer == null || !layer.GetRenderingEnabled() || !addedSceneLayers.Contains(layer))
                {
                    continue;
                }

                materialFilteringWorkspace[curMID.ModelIndex].Add(curMID.Transform);
                ++numInstances;
            }

            // Concatenate & queue render commands
            if (instanceConcatWorkspace == null || instanceConcatWorkspace.Length < numInstances)
            {
                instanceConcatWorkspace = new Matrix[numInstances << 1];                 // x2 so we don't create loads of garbage if the count keeps increasing by 1
            }

            uint instanceStartOffset = RenderCache_IterateMaterial_ConcatReserve(numInstances);
            uint nextWorkspaceIndex = 0;
            uint outVBStartIndex, outIBStartIndex, outVBCount, outIBCount;

            for (uint mI = 0U; mI < materialFilteringWorkspace.Length; ++mI)
            {
                FastClearList <Transform> filteredTransformList = materialFilteringWorkspace[mI];
                int numFilteredTransforms = filteredTransformList.Count;
                if (numFilteredTransforms == 0)
                {
                    continue;
                }

                currentCache.GetModelBufferValues(mI, out outVBStartIndex, out outIBStartIndex, out outVBCount, out outIBCount);

                QueueRenderCommand(RenderCommand.DrawIndexedInstanced(
                                       (int)outVBStartIndex,
                                       outIBStartIndex,
                                       outIBCount,
                                       nextWorkspaceIndex + instanceStartOffset,
                                       (uint)numFilteredTransforms
                                       ));

                for (int iI = 0; iI < numFilteredTransforms; ++iI)
                {
                    instanceConcatWorkspace[nextWorkspaceIndex++] = filteredTransformList[iI].AsMatrixTransposed;
                }
            }

            RenderCache_IterateMaterial_Concat(instanceConcatWorkspace, instanceStartOffset, numInstances);
        }