/// <inheritdoc/>
        public override void Prepare(RenderThreadContext context)
        {
            // Assign descriptor sets to each render node
            var resourceGroupPool = ((RootEffectRenderFeature)RootRenderFeature).ResourceGroupPool;

            for (int renderNodeIndex = 0; renderNodeIndex < RootRenderFeature.RenderNodes.Count; renderNodeIndex++)
            {
                var renderNodeReference = new RenderNodeReference(renderNodeIndex);
                var renderNode          = RootRenderFeature.RenderNodes[renderNodeIndex];
                var renderMesh          = (RenderMesh)renderNode.RenderObject;

                // Ignore fallback effects
                if (renderNode.RenderEffect.State != RenderEffectState.Normal)
                {
                    continue;
                }

                // Collect materials and create associated MaterialInfo (includes reflection) first time
                // TODO: We assume same material will generate same ResourceGroup (i.e. same resources declared in same order)
                // Need to offer some protection if this invariant is violated (or support it if it can actually happen in real scenario)
                var material           = renderMesh.Material;
                var materialInfo       = renderMesh.MaterialInfo;
                var materialParameters = material.Parameters;

                if (!UpdateMaterial(RenderSystem, context, materialInfo, perMaterialDescriptorSetSlot.Index, renderNode.RenderEffect, materialParameters))
                {
                    continue;
                }

                var descriptorSetPoolOffset = ((RootEffectRenderFeature)RootRenderFeature).ComputeResourceGroupOffset(renderNodeReference);
                resourceGroupPool[descriptorSetPoolOffset + perMaterialDescriptorSetSlot.Index] = materialInfo.Resources;
            }
        }
        /// <inheritdoc/>
        public override void Prepare(RenderThreadContext context)
        {
            var renderViewObjectInfoData = RootRenderFeature.RenderData.GetData(renderViewObjectInfoKey);

            var resourceGroupPool = ((RootEffectRenderFeature)RootRenderFeature).ResourceGroupPool;

            for (int renderNodeIndex = 0; renderNodeIndex < RootRenderFeature.RenderNodes.Count; renderNodeIndex++)
            {
                var renderNodeReference  = new RenderNodeReference(renderNodeIndex);
                var renderNode           = RootRenderFeature.RenderNodes[renderNodeIndex];
                var renderViewObjectInfo = renderViewObjectInfoData[renderNode.ViewObjectNode];

                if (renderViewObjectInfo == null)
                {
                    continue;
                }

                // Ignore fallback effects
                if (renderNode.RenderEffect.State != RenderEffectState.Normal)
                {
                    continue;
                }

                if (!PrepareLightParameterEntry(context, renderViewObjectInfo, renderNode.RenderEffect))
                {
                    continue;
                }

                var resourceGroupPoolOffset = ((RootEffectRenderFeature)RootRenderFeature).ComputeResourceGroupOffset(renderNodeReference);
                resourceGroupPool[resourceGroupPoolOffset + perLightingDescriptorSetSlot.Index] = renderViewObjectInfo.Resources;
            }
        }
Exemple #3
0
        /// <param name="context"></param>
        /// <inheritdoc/>
        public override void PrepareEffectPermutationsImpl(RenderThreadContext context)
        {
            var renderEffects = RenderData.GetData(RenderEffectKey);

            foreach (var renderObject in RenderObjects)
            {
                var staticObjectNode = renderObject.StaticObjectNode;

                for (int i = 0; i < EffectPermutationSlotCount; ++i)
                {
                    var staticEffectObjectNode = staticObjectNode * EffectPermutationSlotCount + i;
                    var renderEffect           = renderEffects[staticEffectObjectNode];
                    var renderSkybox           = (RenderSkybox)renderObject;

                    // Skip effects not used during this frame
                    if (renderEffect == null || !renderEffect.IsUsedDuringThisFrame(RenderSystem))
                    {
                        continue;
                    }

                    var parameters = renderSkybox.Background == SkyboxBackground.Irradiance ? renderSkybox.Skybox.DiffuseLightingParameters : renderSkybox.Skybox.Parameters;

                    var shader = parameters.Get(SkyboxKeys.Shader);

                    if (shader == null)
                    {
                        renderEffect.EffectValidator.ShouldSkip = true;
                    }
                    renderEffect.EffectValidator.ValidateParameter(SkyboxKeys.Shader, shader);
                }
            }

            transformRenderFeature.PrepareEffectPermutations(context);
        }
Exemple #4
0
        /// <inheritdoc/>
        public override void PrepareEffectPermutationsImpl(RenderThreadContext context)
        {
            base.PrepareEffectPermutationsImpl(context);

            var renderEffects   = RenderData.GetData(renderEffectKey);
            int effectSlotCount = EffectPermutationSlotCount;

            // Update existing materials
            foreach (var material in allMaterialInfos)
            {
                material.Key.Setup(RenderSystem.RenderContextOld);
            }

            foreach (var renderObject in RenderObjects)
            {
                var staticObjectNode      = renderObject.StaticObjectNode;
                var renderParticleEmitter = (RenderParticleEmitter)renderObject;

                var material     = renderParticleEmitter.ParticleEmitter.Material;
                var materialInfo = renderParticleEmitter.ParticleMaterialInfo;

                for (int i = 0; i < effectSlotCount; ++i)
                {
                    var staticEffectObjectNode = staticObjectNode * effectSlotCount + i;
                    var renderEffect           = renderEffects[staticEffectObjectNode];

                    // Skip effects not used during this frame
                    if (renderEffect == null || !renderEffect.IsUsedDuringThisFrame(RenderSystem))
                    {
                        continue;
                    }

                    if (materialInfo == null || materialInfo.Material != material)
                    {
                        // First time this material is initialized, let's create associated info
                        if (!allMaterialInfos.TryGetValue(material, out materialInfo))
                        {
                            materialInfo = new ParticleMaterialInfo(material);
                            allMaterialInfos.Add(material, materialInfo);
                        }
                        renderParticleEmitter.ParticleMaterialInfo = materialInfo;

                        // Update new materials
                        material.Setup(RenderSystem.RenderContextOld);
                    }

                    // TODO: Iterate PermuatationParameters automatically?
                    material.ValidateEffect(RenderSystem.RenderContextOld, ref renderEffect.EffectValidator);
                }
            }
        }
Exemple #5
0
    void SinglePassPreRender()
    {
        if (needInitPropertyId)
        {
            id_unity_StereoCameraProjection    = Shader.PropertyToID("unity_StereoCameraProjection");
            id_unity_StereoCameraInvProjection = Shader.PropertyToID("unity_StereoCameraInvProjection");
            id_unity_StereoMatrixP             = Shader.PropertyToID("unity_StereoMatrixP");
            id_unity_StereoCameraToWorld       = Shader.PropertyToID("unity_StereoCameraToWorld");
            id_unity_StereoWorldToCamera       = Shader.PropertyToID("unity_StereoWorldToCamera");
            id_unity_StereoWorldSpaceCameraPos = Shader.PropertyToID("unity_StereoWorldSpaceCameraPos");
            id_unity_StereoMatrixV             = Shader.PropertyToID("unity_StereoMatrixV");
            id_unity_StereoMatrixInvV          = Shader.PropertyToID("unity_StereoMatrixInvV");
            id_unity_StereoMatrixVP            = Shader.PropertyToID("unity_StereoMatrixVP");
            id_unity_StereoScaleOffset         = Shader.PropertyToID("unity_StereoScaleOffset");

            needInitPropertyId = false;
        }

        var texturepool = WaveVR_Render.Instance.textureManager.both;

        RenderThreadContext.IssueUpdateConfig(RTSOUpdateConfig,
                                              (uint)texturepool.currentPtr,
                                              (uint)texturepool.currentDepthPtr,
                                              cam.allowMSAA ? QualitySettings.antiAliasing : 0);

        // TODO The matrix process here is too slow and cause many GL.Allocate().

        //Unity will not handle these Stereo shader variables for us, so we have to set it all by ourselves

        Shader.SetGlobalMatrixArray(id_unity_StereoCameraProjection, unity_StereoMatrixP);
        Shader.SetGlobalMatrixArray(id_unity_StereoCameraInvProjection, unity_StereoMatrixInvP);
        Shader.SetGlobalMatrixArray(id_unity_StereoMatrixP, unity_StereoMatrixP);

        //Since eyes are moving, so below variables need to re-calculate every frame.
        Matrix4x4 world2Camera = cam.worldToCameraMatrix;          // View matrix
        Matrix4x4 camera2World = cam.cameraToWorldMatrix;

        M4Multiply(ref unity_StereoCameraToWorld[0], ref camera2World, ref eyesOffsetMatrix[0]);
        M4Multiply(ref unity_StereoCameraToWorld[1], ref camera2World, ref eyesOffsetMatrix[1]);

        M4Multiply(ref unity_StereoWorldToCamera[0], ref eyesOffsetMatrixInv[0], ref world2Camera);
        M4Multiply(ref unity_StereoWorldToCamera[1], ref eyesOffsetMatrixInv[1], ref world2Camera);

        // TODO Need to know if this can help set shader...
        //SetStereoViewAndCullingMatrix(unity_StereoWorldToCamera[0], unity_StereoWorldToCamera[1]);

        // Put later than SetStereoViewMatrix() to avoid be overrided.
        Shader.SetGlobalMatrixArray(id_unity_StereoCameraToWorld, unity_StereoCameraToWorld);
        Shader.SetGlobalMatrixArray(id_unity_StereoWorldToCamera, unity_StereoWorldToCamera);

        //So the camera positons
        Vector4 campos = cam.transform.position;

        V4Add(ref stereoWorldSpaceCameraPos[0], ref campos, ref eyesOffset[0]);
        V4Add(ref stereoWorldSpaceCameraPos[1], ref campos, ref eyesOffset[1]);

        Shader.SetGlobalVectorArray(id_unity_StereoWorldSpaceCameraPos, stereoWorldSpaceCameraPos);

        //camera.worldToCameraMatrix is the view matrix
        Shader.SetGlobalMatrixArray(id_unity_StereoMatrixV, unity_StereoWorldToCamera);
        Shader.SetGlobalMatrixArray(id_unity_StereoMatrixInvV, unity_StereoCameraToWorld);

        //MatrixVP is the value UNITY_MATRIX_VP used in shader
        M4Multiply(ref unity_StereoMatrixVP[0], ref unity_StereoMatrixP[0], ref unity_StereoWorldToCamera[0]);
        M4Multiply(ref unity_StereoMatrixVP[1], ref unity_StereoMatrixP[1], ref unity_StereoWorldToCamera[1]);

        Shader.SetGlobalMatrixArray(id_unity_StereoMatrixVP, unity_StereoMatrixVP);

        Shader.SetGlobalVectorArray(id_unity_StereoScaleOffset, unity_StereoScaleOffset);

        PrepareCommandBuffers();
    }
Exemple #6
0
 public void CopyTo(RenderThreadContext dest)
 {
     dest.antialiasing = antialiasing;
     dest.textureId    = textureId;
     dest.depthId      = depthId;
 }
        private unsafe bool PrepareLightParameterEntry(RenderThreadContext context, LightParametersPermutationEntry lightParameterEntry, RenderEffect renderEffect)
        {
            var lightShadersPermutation = lightParameterEntry.ShaderPermutationEntry;

            // Create layout for new light shader permutations
            if (lightShadersPermutation.PerLightingLayout == null || lightShadersPermutation.PerLightingLayout.Hash != renderEffect.Reflection.ResourceGroupDescriptions[perLightingDescriptorSetSlot.Index].Hash)
            {
                var resourceGroupDescription = renderEffect.Reflection.ResourceGroupDescriptions[perLightingDescriptorSetSlot.Index];
                if (resourceGroupDescription.DescriptorSetLayout == null)
                {
                    return(false);
                }

                var parameterCollectionLayout = lightShadersPermutation.ParameterCollectionLayout = new ParameterCollectionLayout();
                parameterCollectionLayout.ProcessResources(resourceGroupDescription.DescriptorSetLayout);
                lightShadersPermutation.ResourceCount = parameterCollectionLayout.ResourceCount;

                // Process PerLighting cbuffer (if any)
                if (resourceGroupDescription.ConstantBufferReflection != null)
                {
                    lightShadersPermutation.ConstantBufferReflection = resourceGroupDescription.ConstantBufferReflection;
                    parameterCollectionLayout.ProcessConstantBuffer(resourceGroupDescription.ConstantBufferReflection);
                }

                lightShadersPermutation.PerLightingLayout = ResourceGroupLayout.New(RenderSystem.GraphicsDevice, resourceGroupDescription, renderEffect.Effect.Bytecode);
            }

            // Assign layout to new parameter permutations
            var parameters = lightParameterEntry.Parameters;

            if (parameters.Layout != lightShadersPermutation.ParameterCollectionLayout)
            {
                // TODO GRAPHICS REFACTOR should we recompute or store the parameter layout?
                parameters.UpdateLayout(lightShadersPermutation.ParameterCollectionLayout);
            }

            // Do we need to allocate resources?
            if (lightParameterEntry.LastFrameUsed == RenderSystem.FrameCounter)
            {
                return(true);
            }

            lightParameterEntry.LastFrameUsed = RenderSystem.FrameCounter;

            // Set values
            foreach (var lightGroup in lightParameterEntry.DirectLightGroupDatas)
            {
                lightGroup.ApplyParameters(parameters);
            }

            foreach (var lightGroup in lightParameterEntry.EnvironmentLightDatas)
            {
                lightGroup.ApplyParameters(parameters);
            }

            context.ResourceGroupAllocator.PrepareResourceGroup(lightShadersPermutation.PerLightingLayout, BufferPoolAllocationType.UsedMultipleTime, lightParameterEntry.Resources);

            // Set resource bindings in PerLighting resource set
            for (int resourceSlot = 0; resourceSlot < lightShadersPermutation.ResourceCount; ++resourceSlot)
            {
                lightParameterEntry.Resources.DescriptorSet.SetValue(resourceSlot, parameters.ObjectValues[resourceSlot]);
            }

            // Process PerMaterial cbuffer
            if (lightShadersPermutation.ConstantBufferReflection != null)
            {
                var mappedCB = lightParameterEntry.Resources.ConstantBuffer.Data;

                fixed(byte *dataValues = parameters.DataValues)
                Utilities.CopyMemory(mappedCB, (IntPtr)dataValues, lightParameterEntry.Resources.ConstantBuffer.Size);
            }

            return(true);
        }
        /// <param name="context"></param>
        /// <inheritdoc/>
        public override void PrepareEffectPermutations(RenderThreadContext context)
        {
            var renderEffects            = RootRenderFeature.RenderData.GetData(renderEffectKey);
            int effectSlotCount          = ((RootEffectRenderFeature)RootRenderFeature).EffectPermutationSlotCount;
            var renderViewObjectInfoData = RootRenderFeature.RenderData.GetData(renderViewObjectInfoKey);

            var shadowMapEffectSlot = ShadowMapRenderStage != null ? ((RootEffectRenderFeature)RootRenderFeature).GetEffectPermutationSlot(ShadowMapRenderStage) : EffectPermutationSlot.Invalid;

            foreach (var view in RenderSystem.Views)
            {
                if (view.GetType() != typeof(RenderView))
                {
                    continue;
                }

                RenderViewLightData renderViewData;
                if (!renderViewDatas.TryGetValue(view, out renderViewData))
                {
                    continue;
                }

                var viewFeature = view.Features[RootRenderFeature.Index];

                foreach (var renderPerViewNodeReference in viewFeature.ViewObjectNodes)
                {
                    var renderPerViewNode = RootRenderFeature.GetViewObjectNode(renderPerViewNodeReference);

                    var renderMesh = (RenderMesh)renderPerViewNode.RenderObject;

                    if (!renderMesh.Material.IsLightDependent)
                    {
                        continue;
                    }

                    var staticObjectNode = renderMesh.StaticObjectNode;

                    for (int i = 0; i < effectSlotCount; ++i)
                    {
                        // Don't apply lighting for shadow casters
                        if (i == shadowMapEffectSlot.Index)
                        {
                            continue;
                        }

                        var staticEffectObjectNode = staticObjectNode * effectSlotCount + i;
                        var renderEffect           = renderEffects[staticEffectObjectNode];

                        // Skip effects not used during this frame
                        if (renderEffect == null || !renderEffect.IsUsedDuringThisFrame(RenderSystem))
                        {
                            continue;
                        }

                        var renderModel      = renderMesh.RenderModel;
                        var modelComponent   = renderModel.ModelComponent;
                        var isShadowReceiver = renderMesh.IsShadowReceiver && modelComponent.IsShadowReceiver;

                        // TODO GRAPHICS REFACTOR: Shader permutations can be collected per-object. Only parameter permutations need to be per-view-object.
                        var renderObjectInfo = PreparePermutationEntryForRendering(renderViewData, isShadowReceiver, ref modelComponent.BoundingBox, modelComponent.Entity.Group, i);
                        renderObjectInfo.ApplyEffectPermutations(renderEffect);
                        renderViewObjectInfoData[renderPerViewNodeReference] = renderObjectInfo;

                        if (renderObjectInfo == null)
                        {
                            continue;
                        }

                        renderEffect.EffectValidator.ValidateParameter(LightingKeys.DirectLightGroups, renderObjectInfo.ShaderPermutationEntry.DirectLightShaders);
                        renderEffect.EffectValidator.ValidateParameter(LightingKeys.EnvironmentLights, renderObjectInfo.ShaderPermutationEntry.EnvironmentLightShaders);
                    }
                }
            }
        }
Exemple #9
0
        /// <inheritdoc/>
        public override unsafe void Prepare(RenderThreadContext context)
        {
            base.Prepare(context);

            for (int renderNodeIndex = 0; renderNodeIndex < RenderNodes.Count; renderNodeIndex++)
            {
                var renderNodeReference = new RenderNodeReference(renderNodeIndex);
                var renderNode          = RenderNodes[renderNodeIndex];

                var renderSkybox     = (RenderSkybox)renderNode.RenderObject;
                var sourceParameters = renderSkybox.Background == SkyboxBackground.Irradiance ? renderSkybox.Skybox.DiffuseLightingParameters : renderSkybox.Skybox.Parameters;

                var skyboxInfo = renderSkybox.SkyboxInfo;
                if (skyboxInfo == null || skyboxInfo.Skybox != renderSkybox.Skybox)
                {
                    skyboxInfo = renderSkybox.SkyboxInfo = new SkyboxInfo(renderSkybox.Skybox);
                }

                var parameters = skyboxInfo.ParameterCollection;

                var renderEffect = renderNode.RenderEffect;
                if (renderEffect.State != RenderEffectState.Normal)
                {
                    continue;
                }

                // TODO GRAPHICS REFACTOR current system is not really safe with multiple renderers (parameters come from Skybox which is shared but ResourceGroupLayout from RenderSkybox is per RenderNode)
                if (skyboxInfo.ResourceGroupLayout == null || skyboxInfo.ResourceGroupLayout.Hash != renderEffect.Reflection.ResourceGroupDescriptions[perLightingDescriptorSetSlot.Index].Hash)
                {
                    var resourceGroupDescription = renderEffect.Reflection.ResourceGroupDescriptions[perLightingDescriptorSetSlot.Index];

                    var parameterCollectionLayout = skyboxInfo.ParameterCollectionLayout = new ParameterCollectionLayout();
                    parameterCollectionLayout.ProcessResources(resourceGroupDescription.DescriptorSetLayout);

                    // Find material cbuffer
                    if (resourceGroupDescription.ConstantBufferReflection != null)
                    {
                        parameterCollectionLayout.ProcessConstantBuffer(resourceGroupDescription.ConstantBufferReflection);
                    }

                    //skyboxInfo.RotationParameter = parameters.GetAccessor(SkyboxKeys.Rotation);
                    //skyboxInfo.SkyMatrixParameter = parameters.GetAccessor(SkyboxKeys.SkyMatrix);

                    // TODO: Cache that
                    skyboxInfo.ResourceGroupLayout = ResourceGroupLayout.New(RenderSystem.GraphicsDevice, resourceGroupDescription, renderEffect.Effect.Bytecode);

                    parameters.UpdateLayout(parameterCollectionLayout);

                    if (renderSkybox.Background == SkyboxBackground.Irradiance)
                    {
                        skyboxInfo.ParameterCollectionCopier = new ParameterCollection.Copier(parameters, sourceParameters, ".skyboxColor");
                    }
                    else
                    {
                        skyboxInfo.ParameterCollectionCopier = new ParameterCollection.Copier(parameters, sourceParameters);
                    }
                }

                skyboxInfo.ParameterCollectionCopier.Copy();

                // Setup the intensity
                parameters.Set(SkyboxKeys.Intensity, renderSkybox.Intensity);

                // Update SkyMatrix
                Matrix skyMatrix;
                Matrix.RotationQuaternion(ref renderSkybox.Rotation, out skyMatrix);
                parameters.Set(SkyboxKeys.SkyMatrix, ref skyMatrix);

                // Update MatrixTransform
                // TODO: Use default values?
                var matrixTransformOffset = renderNode.RenderEffect.Reflection.PerDrawLayout.GetConstantBufferOffset(this.matrixTransform);
                if (matrixTransformOffset != -1)
                {
                    var mappedCB = renderNode.Resources.ConstantBuffer.Data + matrixTransformOffset;
                    Matrix.Translation(0.0f, 0.0f, 1.0f, out *(Matrix *)(byte *)mappedCB);
                }

                var descriptorSetPoolOffset = ComputeResourceGroupOffset(renderNodeReference);
                context.ResourceGroupAllocator.PrepareResourceGroup(skyboxInfo.ResourceGroupLayout, BufferPoolAllocationType.UsedMultipleTime, skyboxInfo.Resources);
                ResourceGroupPool[descriptorSetPoolOffset + perLightingDescriptorSetSlot.Index] = skyboxInfo.Resources;

                var descriptorSet = skyboxInfo.Resources.DescriptorSet;

                // Set resource bindings in PerLighting resource set
                for (int resourceSlot = 0; resourceSlot < parameters.Layout.ResourceCount; ++resourceSlot)
                {
                    descriptorSet.SetValue(resourceSlot, parameters.ObjectValues[resourceSlot]);
                }

                // Process PerLighting cbuffer
                if (skyboxInfo.Resources.ConstantBuffer.Size > 0)
                {
                    var mappedCB = skyboxInfo.Resources.ConstantBuffer.Data;

                    fixed(byte *dataValues = parameters.DataValues)
                    Utilities.CopyMemory(mappedCB, (IntPtr)dataValues, skyboxInfo.Resources.ConstantBuffer.Size);
                }
            }

            transformRenderFeature.Prepare(context);
        }
        /// <param name="context"></param>
        /// <inheritdoc/>
        public override void PrepareEffectPermutations(RenderThreadContext context)
        {
            var renderEffects      = RootRenderFeature.RenderData.GetData(renderEffectKey);
            var tessellationStates = RootRenderFeature.RenderData.GetData(tessellationStateKey);
            int effectSlotCount    = ((RootEffectRenderFeature)RootRenderFeature).EffectPermutationSlotCount;

            foreach (var renderObject in RootRenderFeature.RenderObjects)
            {
                var staticObjectNode = renderObject.StaticObjectNode;

                var renderMesh = (RenderMesh)renderObject;

                var material     = renderMesh.Material;
                var materialInfo = renderMesh.MaterialInfo;

                // Material use first 16 bits
                var materialHashCode = material != null ? (uint)material.GetHashCode() : 0;
                renderObject.StateSortKey = (renderObject.StateSortKey & 0x0000FFFF) | (materialHashCode << 16);

                var tessellationState = tessellationStates[staticObjectNode];

                // Update draw data if tessellation is active
                if (material.TessellationMethod != XenkoTessellationMethod.None)
                {
                    var tessellationMeshDraw = tessellationState.MeshDraw;

                    if (tessellationState.Method != material.TessellationMethod)
                    {
                        tessellationState.Method = material.TessellationMethod;

                        var oldMeshDraw = renderMesh.ActiveMeshDraw;
                        tessellationMeshDraw = new MeshDraw
                        {
                            VertexBuffers = oldMeshDraw.VertexBuffers,
                            IndexBuffer   = oldMeshDraw.IndexBuffer,
                            DrawCount     = oldMeshDraw.DrawCount,
                            StartLocation = oldMeshDraw.StartLocation,
                            PrimitiveType = tessellationState.Method.GetPrimitiveType(),
                        };

                        // adapt the primitive type and index buffer to the tessellation used
                        if (tessellationState.Method.PerformsAdjacentEdgeAverage())
                        {
                            renderMeshesToGenerateAEN.Add(renderMesh);
                        }
                        else
                        {
                            // Not using AEN tessellation anymore, dispose AEN indices if they were generated
                            Utilities.Dispose(ref tessellationState.GeneratedIndicesAEN);
                        }
                        tessellationState.MeshDraw = tessellationMeshDraw;

                        // Save back new state
                        tessellationStates[staticObjectNode] = tessellationState;

                        // Reset pipeline states
                        for (int i = 0; i < effectSlotCount; ++i)
                        {
                            var staticEffectObjectNode = staticObjectNode * effectSlotCount + i;
                            var renderEffect           = renderEffects[staticEffectObjectNode];

                            if (renderEffect != null)
                            {
                                renderEffect.PipelineState = null;
                            }
                        }
                    }

                    renderMesh.ActiveMeshDraw = tessellationState.MeshDraw;
                }
                else if (tessellationState.GeneratedIndicesAEN != null)
                {
                    // Not using tessellation anymore, dispose AEN indices if they were generated
                    Utilities.Dispose(ref tessellationState.GeneratedIndicesAEN);
                }

                for (int i = 0; i < effectSlotCount; ++i)
                {
                    var staticEffectObjectNode = staticObjectNode * effectSlotCount + i;
                    var renderEffect           = renderEffects[staticEffectObjectNode];

                    // Skip effects not used during this frame
                    if (renderEffect == null || !renderEffect.IsUsedDuringThisFrame(RenderSystem))
                    {
                        continue;
                    }

                    if (materialInfo == null || materialInfo.Material != material)
                    {
                        // First time this material is initialized, let's create associated info
                        if (!allMaterialInfos.TryGetValue(material, out materialInfo))
                        {
                            materialInfo = new MaterialInfo(material);
                            allMaterialInfos.Add(material, materialInfo);
                        }
                        renderMesh.MaterialInfo = materialInfo;
                    }

                    if (materialInfo.CullMode != material.CullMode)
                    {
                        materialInfo.CullMode      = material.CullMode;
                        renderEffect.PipelineState = null;
                    }

                    var isMaterialParametersChanged = materialInfo.MaterialParameters != material.Parameters;
                    if (isMaterialParametersChanged || // parameter fast reload?
                        materialInfo.PermutationCounter != material.Parameters.PermutationCounter)
                    {
                        materialInfo.VertexStageSurfaceShaders    = material.Parameters.Get(MaterialKeys.VertexStageSurfaceShaders);
                        materialInfo.VertexStageStreamInitializer = material.Parameters.Get(MaterialKeys.VertexStageStreamInitializer);

                        materialInfo.DomainStageSurfaceShaders    = material.Parameters.Get(MaterialKeys.DomainStageSurfaceShaders);
                        materialInfo.DomainStageStreamInitializer = material.Parameters.Get(MaterialKeys.DomainStageStreamInitializer);

                        materialInfo.TessellationShader = material.Parameters.Get(MaterialKeys.TessellationShader);

                        materialInfo.PixelStageSurfaceShaders    = material.Parameters.Get(MaterialKeys.PixelStageSurfaceShaders);
                        materialInfo.PixelStageStreamInitializer = material.Parameters.Get(MaterialKeys.PixelStageStreamInitializer);
                        materialInfo.HasNormalMap = material.Parameters.Get(MaterialKeys.HasNormalMap);

                        materialInfo.MaterialParameters = material.Parameters;
                        materialInfo.ParametersChanged  = isMaterialParametersChanged;
                        materialInfo.PermutationCounter = material.Parameters.PermutationCounter;
                    }

                    // VS
                    if (materialInfo.VertexStageSurfaceShaders != null)
                    {
                        renderEffect.EffectValidator.ValidateParameter(MaterialKeys.VertexStageSurfaceShaders, materialInfo.VertexStageSurfaceShaders);
                    }
                    if (materialInfo.VertexStageStreamInitializer != null)
                    {
                        renderEffect.EffectValidator.ValidateParameter(MaterialKeys.VertexStageStreamInitializer, materialInfo.VertexStageStreamInitializer);
                    }

                    // DS
                    if (materialInfo.DomainStageSurfaceShaders != null)
                    {
                        renderEffect.EffectValidator.ValidateParameter(MaterialKeys.DomainStageSurfaceShaders, materialInfo.DomainStageSurfaceShaders);
                    }
                    if (materialInfo.DomainStageStreamInitializer != null)
                    {
                        renderEffect.EffectValidator.ValidateParameter(MaterialKeys.DomainStageStreamInitializer, materialInfo.DomainStageStreamInitializer);
                    }

                    // Tessellation
                    if (materialInfo.TessellationShader != null)
                    {
                        renderEffect.EffectValidator.ValidateParameter(MaterialKeys.TessellationShader, materialInfo.TessellationShader);
                    }

                    // PS
                    if (materialInfo.PixelStageSurfaceShaders != null)
                    {
                        renderEffect.EffectValidator.ValidateParameter(MaterialKeys.PixelStageSurfaceShaders, materialInfo.PixelStageSurfaceShaders);
                    }
                    if (materialInfo.PixelStageStreamInitializer != null)
                    {
                        renderEffect.EffectValidator.ValidateParameter(MaterialKeys.PixelStageStreamInitializer, materialInfo.PixelStageStreamInitializer);
                    }
                    if (materialInfo.HasNormalMap)
                    {
                        renderEffect.EffectValidator.ValidateParameter(MaterialKeys.HasNormalMap, materialInfo.HasNormalMap);
                    }
                }
            }
        }
        public static unsafe bool UpdateMaterial(RenderSystem renderSystem, RenderThreadContext context, MaterialInfoBase materialInfo, int materialSlotIndex, RenderEffect renderEffect, ParameterCollection materialParameters)
        {
            // Check if encountered first time this frame
            if (materialInfo.LastFrameUsed == renderSystem.FrameCounter)
            {
                return(true);
            }

            // First time we use the material with a valid effect, let's update layouts
            if (materialInfo.PerMaterialLayout == null || materialInfo.PerMaterialLayout.Hash != renderEffect.Reflection.ResourceGroupDescriptions[materialSlotIndex].Hash)
            {
                var resourceGroupDescription = renderEffect.Reflection.ResourceGroupDescriptions[materialSlotIndex];
                if (resourceGroupDescription.DescriptorSetLayout == null)
                {
                    return(false);
                }

                materialInfo.PerMaterialLayout = ResourceGroupLayout.New(renderSystem.GraphicsDevice, resourceGroupDescription, renderEffect.Effect.Bytecode);

                var parameterCollectionLayout = materialInfo.ParameterCollectionLayout = new ParameterCollectionLayout();
                parameterCollectionLayout.ProcessResources(resourceGroupDescription.DescriptorSetLayout);
                materialInfo.ResourceCount = parameterCollectionLayout.ResourceCount;

                // Process material cbuffer (if any)
                if (resourceGroupDescription.ConstantBufferReflection != null)
                {
                    materialInfo.ConstantBufferReflection = resourceGroupDescription.ConstantBufferReflection;
                    parameterCollectionLayout.ProcessConstantBuffer(resourceGroupDescription.ConstantBufferReflection);
                }
                materialInfo.ParametersChanged = true;
            }

            // If the parameters collection instance changed, we need to update it
            if (materialInfo.ParametersChanged)
            {
                materialInfo.ParameterCollection.UpdateLayout(materialInfo.ParameterCollectionLayout);
                materialInfo.ParameterCollectionCopier = new ParameterCollection.Copier(materialInfo.ParameterCollection, materialParameters);
                materialInfo.ParametersChanged         = false;
            }

            // Mark this material as used during this frame
            materialInfo.LastFrameUsed = renderSystem.FrameCounter;

            // Copy back to ParameterCollection
            // TODO GRAPHICS REFACTOR directly copy to resource group?
            materialInfo.ParameterCollectionCopier.Copy();

            // Allocate resource groups
            context.ResourceGroupAllocator.PrepareResourceGroup(materialInfo.PerMaterialLayout, BufferPoolAllocationType.UsedMultipleTime, materialInfo.Resources);

            // Set resource bindings in PerMaterial resource set
            for (int resourceSlot = 0; resourceSlot < materialInfo.ResourceCount; ++resourceSlot)
            {
                materialInfo.Resources.DescriptorSet.SetValue(resourceSlot, materialInfo.ParameterCollection.ObjectValues[resourceSlot]);
            }

            // Process PerMaterial cbuffer
            if (materialInfo.ConstantBufferReflection != null)
            {
                var mappedCB = materialInfo.Resources.ConstantBuffer.Data;

                fixed(byte *dataValues = materialInfo.ParameterCollection.DataValues)
                Utilities.CopyMemory(mappedCB, (IntPtr)dataValues, materialInfo.Resources.ConstantBuffer.Size);
            }

            return(true);
        }
Exemple #12
0
        /// <inheritdoc/>
        public override unsafe void Prepare(RenderThreadContext context)
        {
            // Reset pipeline states if necessary
            for (int renderNodeIndex = 0; renderNodeIndex < RenderNodes.Count; renderNodeIndex++)
            {
                var renderNode            = RenderNodes[renderNodeIndex];
                var renderParticleEmitter = (RenderParticleEmitter)renderNode.RenderObject;

                if (renderParticleEmitter.ParticleEmitter.VertexBuilder.IsBufferDirty)
                {
                    // Reset pipeline state, so input layout is regenerated
                    if (renderNode.RenderEffect != null)
                    {
                        renderNode.RenderEffect.PipelineState = null;
                    }
                }
            }

            foreach (var renderObject in RenderObjects)
            {
                var renderParticleEmitter = (RenderParticleEmitter)renderObject;
                renderParticleEmitter.ParticleEmitter.PrepareForDraw();

                var materialInfo = (ParticleMaterialInfo)renderParticleEmitter.ParticleMaterialInfo;

                // Handle vertex element changes
                if (renderParticleEmitter.ParticleEmitter.VertexBuilder.IsBufferDirty)
                {
                    // Create new buffers
                    renderParticleEmitter.ParticleEmitter.VertexBuilder.RecreateBuffers(RenderSystem.GraphicsDevice);
                }

                // TODO: ParticleMaterial should set this up
                materialInfo?.Material.Parameters.Set(ParticleBaseKeys.ColorScale, renderParticleEmitter.RenderParticleSystem.ParticleSystemComponent.Color);
            }

            base.Prepare(context);

            // Assign descriptor sets to each render node
            var resourceGroupPool = ResourceGroupPool;

            for (int renderNodeIndex = 0; renderNodeIndex < RenderNodes.Count; renderNodeIndex++)
            {
                var renderNodeReference   = new RenderNodeReference(renderNodeIndex);
                var renderNode            = RenderNodes[renderNodeIndex];
                var renderParticleEmitter = (RenderParticleEmitter)renderNode.RenderObject;

                // Ignore fallback effects
                if (renderNode.RenderEffect.State != RenderEffectState.Normal)
                {
                    continue;
                }

                // Collect materials and create associated MaterialInfo (includes reflection) first time
                // TODO: We assume same material will generate same ResourceGroup (i.e. same resources declared in same order)
                // Need to offer some protection if this invariant is violated (or support it if it can actually happen in real scenario)
                var material           = renderParticleEmitter.ParticleEmitter.Material;
                var materialInfo       = renderParticleEmitter.ParticleMaterialInfo;
                var materialParameters = material.Parameters;

                if (!MaterialRenderFeature.UpdateMaterial(RenderSystem, context, materialInfo, perMaterialDescriptorSetSlot.Index, renderNode.RenderEffect, materialParameters))
                {
                    continue;
                }

                var descriptorSetPoolOffset = ComputeResourceGroupOffset(renderNodeReference);
                resourceGroupPool[descriptorSetPoolOffset + perMaterialDescriptorSetSlot.Index] = materialInfo.Resources;
            }

            // Per view
            // TODO: Transform sub render feature?
            for (int index = 0; index < RenderSystem.Views.Count; index++)
            {
                var view        = RenderSystem.Views[index];
                var viewFeature = view.Features[Index];

                // TODO GRAPHICS REFACTOR: Happens in several places
                Matrix.Multiply(ref view.View, ref view.Projection, out view.ViewProjection);

                // Copy ViewProjection to PerFrame cbuffer
                foreach (var viewLayout in viewFeature.Layouts)
                {
                    var viewProjectionOffset = viewLayout.GetConstantBufferOffset(this.view);
                    if (viewProjectionOffset == -1)
                    {
                        continue;
                    }

                    var resourceGroup = viewLayout.Entries[view.Index].Resources;
                    var mappedCB      = resourceGroup.ConstantBuffer.Data;

                    var perView = (Matrix *)((byte *)mappedCB + viewProjectionOffset);
                    *   perView = view.ViewProjection;
                }
            }
        }