/// <summary> /// Uploads the specified device context. This function writes a external struct and writes remains byte buffer /// by offset = input struct size/> /// </summary> /// <typeparam name="T"></typeparam> /// <param name="deviceContext">The device context.</param> /// <param name="data">The data.</param> /// <returns></returns> public bool Upload <T>(DeviceContextProxy deviceContext, ref T data) where T : unmanaged { lock (lck) { if (IsValid && IsAttached) { var structSize = UnsafeHelper.SizeOf <T>(); if (ModelConstBuffer.Buffer.Description.SizeInBytes < structSize) { #if DEBUG throw new ArgumentOutOfRangeException($"Try to write value out of range. StructureSize {structSize}" + $" > Constant Buffer Size {ModelConstBuffer.StructureSize}"); #else return(false); #endif } var box = ModelConstBuffer.Map(deviceContext); unsafe { var pBuf = (byte *)box.DataPointer.ToPointer(); *(T *)pBuf = data; } ModelConstBuffer.Unmap(deviceContext); return(true); } return(false); } }
public void WriteValueByName <T>(string name, T value) where T : unmanaged { if (IsValid && IsAttached) { lock (lck) { if (IsValid && IsAttached) { if (ModelConstBuffer.TryGetVariableByName(name, out var variable)) { if (UnsafeHelper.SizeOf <T>() > variable.Size) { var structSize = UnsafeHelper.SizeOf <T>(); throw new ArgumentException($"Input struct size {structSize} is larger than shader variable {variable.Name} size {variable.Size}"); } if (!storage.Write(storageId, variable.StartOffset, ref value)) { throw new ArgumentException($"Failed to write value on {name}"); } } else { #if DEBUG throw new ArgumentException($"Variable not found in constant buffer {bufferDesc.Name}. Variable = {name}"); #else Technique.EffectsManager.Logger.Log(Logger.LogLevel.Warning, $"Variable not found in constant buffer {bufferDesc.Name}. Variable = {name}"); #endif } } } } }
public bool Read <T>(int id, int offset, out T value) where T : unmanaged { if (id < 0) { value = default; return(false); } var size = UnsafeHelper.SizeOf <T>(); var offsetInArray = GetOffSet(id) + offset; if (offsetInArray + size > binaryArray.Count) { Debug.Assert(false); value = default; return(false); } var array = binaryArray.GetInternalArray(); fixed(byte *pArray = &array[offsetInArray]) { value = *(T *)pArray; } return(true); }
/// <summary> /// Updates the material structure. And upload data to constant buffer /// </summary> /// <typeparam name="T"></typeparam> /// <param name="context">The context.</param> /// <param name="model">The model.</param> public bool UpdateMaterialStruct <T>(DeviceContextProxy context, ref T model) where T : unmanaged { if (!initialized) { return(false); } if (NeedUpdate) { lock (updateLock) { if (NeedUpdate) { UpdateInternalVariables(context); NeedUpdate = false; } } } var structSize = UnsafeHelper.SizeOf <T>(); var box = materialCB.Map(context); UnsafeHelper.Write(box.DataPointer, ref model); var succ = storage.Read(storageId, structSize, box.DataPointer + structSize, storage.StructSize - structSize); materialCB.Unmap(context); return(succ); }
public bool Write <T>(int id, int offset, ref T value) where T : unmanaged { var size = UnsafeHelper.SizeOf <T>(); fixed(T *pValue = &value) { return(Write(id, offset, new IntPtr(pValue), size)); } }
/// <summary> /// Updates the non material structure. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="context">The context.</param> /// <param name="model">The model.</param> /// <returns></returns> public bool UpdateNonMaterialStruct <T>(DeviceContextProxy context, ref T model) where T : unmanaged { if (!initialized) { return(false); } if (UnsafeHelper.SizeOf <T>() != nonMaterialCB.StructureSize) { Debug.Assert(false); return(false); } var box = nonMaterialCB.Map(context); UnsafeHelper.Write(box.DataPointer, ref model); nonMaterialCB.Unmap(context); return(true); }
public void UploadDataToBuffer <T>(DeviceContextProxy context, T[] data, int count, int offset) where T : unmanaged { lock (lockObj) { if (bufferDesc.Usage == ResourceUsage.Dynamic) { Debug.Assert(count * UnsafeHelper.SizeOf <T>() <= buffer.Description.SizeInBytes); var dataBox = context.MapSubresource(buffer, 0, MapMode.WriteDiscard, MapFlags.None); UnsafeHelper.Write(dataBox.DataPointer, data, offset, count); context.UnmapSubresource(buffer, 0); } else { context.UpdateSubresource(data, buffer); } } }
public void WriteValue <T>(string name, ref T value) where T : unmanaged { if (materialCB != null && materialCB.TryGetVariableByName(name, out var variable)) { if (UnsafeHelper.SizeOf <T>() > variable.Size) { var structSize = UnsafeHelper.SizeOf <T>(); throw new ArgumentException($"Input struct size {structSize} is larger than shader variable {variable.Name} size {variable.Size}"); } if (!storage.Write(storageId, variable.StartOffset, ref value)) { throw new ArgumentException($"Failed to write value on {name}"); } } else { #if DEBUG throw new ArgumentException($"Variable not found in constant buffer {materialCB.Name}. Variable = {name}"); #else logger.LogWarning("Variable not found in constant buffer {}. Variable = {}", materialCB.Name, name); #endif } }
public override void Render(RenderContext context, DeviceContextProxy deviceContext) { EnsureTextureResources((int)context.ActualWidth, (int)context.ActualHeight, deviceContext); int texScale = (int)offScreenTextureSize; var viewport = context.Viewport; using (var ds = context.GetOffScreenDS(offScreenTextureSize, DEPTHFORMAT)) { using (var rt0 = context.GetOffScreenRT(offScreenTextureSize, RENDERTARGETFORMAT)) { using (var rt1 = context.GetOffScreenRT(offScreenTextureSize, SSAOTARGETFORMAT)) { var w = (int)(context.ActualWidth / texScale);// Make sure to set correct viewport width/height by quality var h = (int)(context.ActualHeight / texScale); deviceContext.SetRenderTarget(ds, rt0, true, new Color4(0, 0, 0, 1), true, DepthStencilClearFlags.Depth); deviceContext.SetViewport(0, 0, w, h); deviceContext.SetScissorRectangle(0, 0, w, h); IRenderTechnique currTechnique = null; var ssaoPass1 = ShaderPass.NullPass; var frustum = context.BoundingFrustum; for (var i = 0; i < context.RenderHost.PerFrameOpaqueNodesInFrustum.Count; ++i) { var node = context.RenderHost.PerFrameOpaqueNodesInFrustum[i]; if (currTechnique != node.EffectTechnique) { currTechnique = node.EffectTechnique; ssaoPass1 = currTechnique[DefaultPassNames.MeshSSAOPass]; } if (ssaoPass1.IsNULL) { continue; } node.RenderDepth(context, deviceContext, ssaoPass1); } var invProjection = context.ProjectionMatrix.Inverted(); ssaoParam.InvProjection = invProjection; ssaoParam.NoiseScale = new Vector2(w / 4f, h / 4f); ssaoParam.Radius = radius; ssaoParam.TextureScale = texScale; ssaoCB.ModelConstBuffer.UploadDataToBuffer(deviceContext, (dataBox) => { Debug.Assert(UnsafeHelper.SizeOf(kernels) + UnsafeHelper.SizeOf(ref ssaoParam) <= ssaoCB.ModelConstBuffer.bufferDesc.SizeInBytes); var nextPtr = UnsafeHelper.Write(dataBox.DataPointer, kernels, 0, kernels.Length); UnsafeHelper.Write(nextPtr, ref ssaoParam); }); deviceContext.SetRenderTarget(rt1); ssaoPass.BindShader(deviceContext); ssaoPass.BindStates(deviceContext, StateType.All); ssaoPass.PixelShader.BindTexture(deviceContext, ssaoTexSlot, rt0); ssaoPass.PixelShader.BindTexture(deviceContext, noiseTexSlot, ssaoNoiseView); ssaoPass.PixelShader.BindTexture(deviceContext, depthSlot, ds); ssaoPass.PixelShader.BindSampler(deviceContext, surfaceSampleSlot, surfaceSampler); ssaoPass.PixelShader.BindSampler(deviceContext, noiseSamplerSlot, noiseSampler); deviceContext.Draw(4, 0); ssaoPass.PixelShader.BindTexture(deviceContext, depthSlot, null); deviceContext.SetRenderTarget(ssaoView); deviceContext.SetViewport(ref viewport); deviceContext.SetScissorRectangle(ref viewport); ssaoBlur.BindShader(deviceContext); ssaoBlur.BindStates(deviceContext, StateType.All); ssaoBlur.PixelShader.BindTexture(deviceContext, ssaoTexSlot, rt1); ssaoBlur.PixelShader.BindSampler(deviceContext, surfaceSampleSlot, blurSampler); deviceContext.Draw(4, 0); context.SharedResource.SSAOMap = ssaoView; context.RenderHost.SetDefaultRenderTargets(false); deviceContext.SetShaderResource(PixelShader.Type, ssaoTexSlot, ssaoView); } } } }