Exemple #1
0
        public EffectParameterUpdaterLayout(GraphicsDevice graphicsDevice, Effect effect, DescriptorSetLayoutBuilder[] layouts)
        {
            Layouts = layouts;

            // Process constant buffers
            ResourceGroupLayouts = new ResourceGroupLayout[layouts.Length];
            for (int layoutIndex = 0; layoutIndex < layouts.Length; layoutIndex++)
            {
                var layout = layouts[layoutIndex];
                if (layout == null)
                {
                    continue;
                }

                ParameterCollectionLayout.ProcessResources(layout);

                EffectConstantBufferDescription cbuffer = null;

                for (int entryIndex = 0; entryIndex < layout.Entries.Count; ++entryIndex)
                {
                    var layoutEntry = layout.Entries[entryIndex];
                    if (layoutEntry.Class == EffectParameterClass.ConstantBuffer)
                    {
                        // For now we assume first cbuffer will be the main one
                        if (cbuffer == null)
                        {
                            cbuffer = effect.Bytecode.Reflection.ConstantBuffers.First(x => x.Name == layoutEntry.Key.Name);
                            ParameterCollectionLayout.ProcessConstantBuffer(cbuffer);
                        }
                    }
                }

                var resourceGroupDescription = new ResourceGroupDescription(layout, cbuffer);

                ResourceGroupLayouts[layoutIndex] = ResourceGroupLayout.New(graphicsDevice, resourceGroupDescription, effect.Bytecode);
            }
        }
Exemple #2
0
        public static unsafe bool UpdateMaterial(RenderSystem renderSystem, RenderDrawContext context, MaterialInfoBase materialInfo, int materialSlotIndex, RenderEffect renderEffect, ParameterCollection materialParameters)
        {
            var resourceGroupDescription = renderEffect.Reflection.ResourceGroupDescriptions[materialSlotIndex];

            if (resourceGroupDescription.DescriptorSetLayout == null)
            {
                return(false);
            }

            // Check if this material was encountered for the first time this frame and mark it as used
            if (Interlocked.Exchange(ref materialInfo.LastFrameUsed, renderSystem.FrameCounter) == 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)
            {
                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;
            }

            // 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 #3
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);
        }
        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);
        }
        public void PrepareResourceGroup(ResourceGroupLayout resourceGroupLayout, BufferPoolAllocationType constantBufferAllocationType, ResourceGroup resourceGroup)
        {
            if (resourceGroup == null)
                throw new InvalidOperationException();

            resourceGroup.DescriptorSet = DescriptorSet.New(graphicsDevice, currentDescriptorPool, resourceGroupLayout.DescriptorSetLayout);
            if (!resourceGroup.DescriptorSet.IsValid)
            {
                SetupNextDescriptorPool();
                resourceGroup.DescriptorSet = DescriptorSet.New(graphicsDevice, currentDescriptorPool, resourceGroupLayout.DescriptorSetLayout);
            }

            if (resourceGroupLayout.ConstantBufferSize > 0)
            {
                if (currentBufferPool == null || !currentBufferPool.CanAllocate(resourceGroupLayout.ConstantBufferSize))
                {
                    SetupNextBufferPool();
                }

                currentBufferPool.Allocate(graphicsDevice, resourceGroupLayout.ConstantBufferSize, constantBufferAllocationType, ref resourceGroup.ConstantBuffer);
            }
        }