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); } }
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 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); }
/// <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); }