Example #1
0
    void LightingParser_ResolveGBuffer(
        Metal::DeviceContext& context, LightingParserContext& parserContext,
        MainTargetsBox& mainTargets, LightingResolveTextureBox& lightingResTargets)
    {
        Metal::GPUProfiler::DebugAnnotation anno(context, L"ResolveGBuffer");

        const bool doSampleFrequencyOptimisation = Tweakable("SampleFrequencyOptimisation", true);

        LightingResolveContext lightingResolveContext(mainTargets);
        const unsigned samplingCount = lightingResolveContext.GetSamplingCount();
        const bool useMsaaSamplers = lightingResolveContext.UseMsaaSamplers();

        auto& resolveRes = Techniques::FindCachedBoxDep2<LightingResolveResources>(samplingCount);

            //
            //    Our inputs is the prepared gbuffer 
            //        -- we resolve the lighting and write out a "lighting resolve texture"
            //

        if (doSampleFrequencyOptimisation && samplingCount>1) {
            context.Bind(resolveRes._alwaysWriteToStencil, 0xff);

                // todo --  instead of clearing the stencil every time, how 
                //          about doing a progressive walk through all of the bits!
            context.ClearStencil(mainTargets._secondaryDepthBuffer, 0);
            context.Bind(ResourceList<Metal::RenderTargetView, 0>(), &mainTargets._secondaryDepthBuffer);
            context.BindPS(MakeResourceList(mainTargets._msaaDepthBufferSRV, mainTargets._gbufferRTVsSRV[1]));
            SetupVertexGeneratorShader(context);
            CATCH_ASSETS_BEGIN
                context.Bind(*resolveRes._perSampleMask);
                context.Draw(4);
            CATCH_ASSETS_END(parserContext)
        }
Example #2
0
    static void DrawTriMeshMarker(
        Metal::DeviceContext& devContext,
        ParsingContext& parserContext,
        const VisGeoBox& visBox,
        const ResolvedShader& shader, const RetainedEntity& obj,
        EntityInterface::RetainedEntities& objs)
    {
        static auto IndexListHash = ParameterBox::MakeParameterNameHash("IndexList");

        if (!obj._properties.GetParameter(Parameters::Visible, true) || !GetShowMarker(obj)) return;

        // we need an index list with at least 3 indices (to make at least one triangle)
        auto indexListType = obj._properties.GetParameterType(IndexListHash);
        if (indexListType._type == ImpliedTyping::TypeCat::Void || indexListType._arrayCount < 3)
            return;

        auto ibData = std::make_unique<unsigned[]>(indexListType._arrayCount);
        bool success = obj._properties.GetParameter(
            IndexListHash, ibData.get(), 
            ImpliedTyping::TypeDesc(ImpliedTyping::TypeCat::UInt32, indexListType._arrayCount));
        if (!success) return;

        const auto& chld = obj._children;
        if (!chld.size()) return;

        auto vbData = std::make_unique<Float3[]>(chld.size());
        for (size_t c=0; c<chld.size(); ++c) {
            const auto* e = objs.GetEntity(obj._doc, chld[c]);
            if (e) {
                vbData[c] = ExtractTranslation(GetTransform(*e));
            } else {
                vbData[c] = Zero<Float3>();
            }
        }
        
        const auto& cbLayout = ::Assets::GetAssetDep<Techniques::PredefinedCBLayout>(
            "game/xleres/BasicMaterialConstants.txt");

        shader.Apply(devContext, parserContext,
            {
                MakeLocalTransformPacket(
                    GetTransform(obj),
                    ExtractTranslation(parserContext.GetProjectionDesc()._cameraToWorld)),
                cbLayout.BuildCBDataAsPkt(ParameterBox())
            });

        devContext.Bind(Techniques::CommonResources()._blendAdditive);
        devContext.Bind(Techniques::CommonResources()._dssReadOnly);
        devContext.Bind(Techniques::CommonResources()._cullDisable);
        
        Metal::VertexBuffer vb(vbData.get(), sizeof(Float3)*chld.size());
        Metal::IndexBuffer ib(ibData.get(), sizeof(unsigned)*indexListType._arrayCount);

        devContext.Bind(MakeResourceList(vb), sizeof(Float3), 0);
        devContext.Bind(ib, Metal::NativeFormat::R32_UINT);
        devContext.Bind(Metal::Topology::TriangleList);
        devContext.DrawIndexed(indexListType._arrayCount);
    }
Example #3
0
 static void AmbientOcclusion_DrawDebugging(
     Metal::DeviceContext& context, AmbientOcclusionResources& resources)
 {
     SetupVertexGeneratorShader(context);
     context.BindPS(MakeResourceList(resources._aoSRV));
     context.Bind(::Assets::GetAssetDep<Metal::ShaderProgram>(
         "game/xleres/basic2D.vsh:fullscreen:vs_*", "game/xleres/postprocess/debugging.psh:AODebugging:ps_*"));
     context.Draw(4);
 }
Example #4
0
    static void DrawObject(
        Metal::DeviceContext& devContext,
        ParsingContext& parserContext,
        const VisGeoBox& visBox,
        const ResolvedShader& shader, const RetainedEntity& obj)
    {
        if (!obj._properties.GetParameter(Parameters::Visible, true) || !GetShowMarker(obj)) return;

        const auto& cbLayout = ::Assets::GetAssetDep<Techniques::PredefinedCBLayout>(
            "game/xleres/BasicMaterialConstants.txt");

        shader.Apply(devContext, parserContext,
            {
                MakeLocalTransformPacket(
                    GetTransform(obj),
                    ExtractTranslation(parserContext.GetProjectionDesc()._cameraToWorld)),
                cbLayout.BuildCBDataAsPkt(ParameterBox())
            });
        
        devContext.Bind(MakeResourceList(visBox._cubeVB), visBox._cubeVBStride, 0);
        devContext.Draw(visBox._cubeVBCount);
    }
Example #5
0
    PreparedRTShadowFrustum PrepareRTShadows(
        IThreadContext& context,
        Metal::DeviceContext& metalContext, 
        LightingParserContext& parserContext,
        PreparedScene& preparedScene,
        const ShadowProjectionDesc& frustum,
        unsigned shadowFrustumIndex)
    {
        SceneParseSettings sceneParseSettings(
            SceneParseSettings::BatchFilter::RayTracedShadows, 
            ~SceneParseSettings::Toggles::BitField(0),
            shadowFrustumIndex);
        if (!parserContext.GetSceneParser()->HasContent(sceneParseSettings))
            return PreparedRTShadowFrustum();

        Metal::GPUProfiler::DebugAnnotation anno(metalContext, L"Prepare-RTShadows");

        auto& box = Techniques::FindCachedBox2<RTShadowsBox>(256, 256, 1024*1024, 32, 64*1024);
        auto oldSO = Metal::GeometryShader::GetDefaultStreamOutputInitializers();
        
        static const Metal::InputElementDesc soVertex[] = 
        {
            Metal::InputElementDesc("A", 0, Metal::NativeFormat::R32G32B32A32_FLOAT),
            Metal::InputElementDesc("B", 0, Metal::NativeFormat::R32G32_FLOAT),
            Metal::InputElementDesc("C", 0, Metal::NativeFormat::R32G32B32A32_FLOAT),
            Metal::InputElementDesc("D", 0, Metal::NativeFormat::R32G32B32_FLOAT)
        };

        static const Metal::InputElementDesc il[] = 
        {
            Metal::InputElementDesc("A", 0, Metal::NativeFormat::R32G32B32A32_FLOAT),
            Metal::InputElementDesc("B", 0, Metal::NativeFormat::R32G32_FLOAT),
            Metal::InputElementDesc("C", 0, Metal::NativeFormat::R32G32B32A32_FLOAT),
            Metal::InputElementDesc("D", 0, Metal::NativeFormat::R32G32B32_FLOAT)
        };

        metalContext.UnbindPS<Metal::ShaderResourceView>(5, 3);

        const unsigned bufferCount = 1;
        unsigned strides[] = { 52 };
        unsigned offsets[] = { 0 };
        Metal::GeometryShader::SetDefaultStreamOutputInitializers(
            Metal::GeometryShader::StreamOutputInitializers(soVertex, dimof(soVertex), strides, 1));

        static_assert(bufferCount == dimof(strides), "Stream output buffer count mismatch");
        static_assert(bufferCount == dimof(offsets), "Stream output buffer count mismatch");
        metalContext.BindSO(MakeResourceList(box._triangleBufferVB));

            // set up the render state for writing into the grid buffer
        SavedTargets savedTargets(metalContext);
        metalContext.Bind(box._gridBufferViewport);
        metalContext.Unbind<Metal::RenderTargetView>();
        metalContext.Bind(Techniques::CommonResources()._blendOpaque);
        metalContext.Bind(Techniques::CommonResources()._defaultRasterizer);    // for newer video cards, we need "conservative raster" enabled

        PreparedRTShadowFrustum preparedResult;
        preparedResult.InitialiseConstants(&metalContext, frustum._projections);
        using TC = Techniques::TechniqueContext;
        parserContext.SetGlobalCB(metalContext, TC::CB_ShadowProjection, &preparedResult._arbitraryCBSource, sizeof(preparedResult._arbitraryCBSource));
        parserContext.SetGlobalCB(metalContext, TC::CB_OrthoShadowProjection, &preparedResult._orthoCBSource, sizeof(preparedResult._orthoCBSource));

        parserContext.GetTechniqueContext()._runtimeState.SetParameter(
            StringShadowCascadeMode, 
            (preparedResult._mode == ShadowProjectionDesc::Projections::Mode::Ortho)?2:1);

            // Now, we need to transform the object's triangle buffer into shadow
            // projection space during this step (also applying skinning, wind bending, and
            // any other animation effects. 
            //
            // Each object that will be used with projected shadows must have a buffer 
            // containing the triangle information.
            //
            // We can deal with this in a number of ways:
            //      1. rtwritetiles shader writes triangles out in a stream-output step
            //      2. transform triangles first, then pass that information through the rtwritetiles shader
            //      3. transform triangles completely separately from the rtwritetiles step
            //
            // Method 1 would avoid extra transformations of the input data, and actually
            // simplifies some of the shader work. We don't need any special input buffers
            // or extra input data. The shaders just take generic model information, and build
            // everything they need, as they need it.
            //
            // We can also choose to reject backfacing triangles at this point, as well as 
            // removing triangles that are culled from the frustum.
            //
        Float4x4 savedWorldToProjection = parserContext.GetProjectionDesc()._worldToProjection;
        parserContext.GetProjectionDesc()._worldToProjection = frustum._worldToClip;
        auto cleanup = MakeAutoCleanup(
            [&parserContext, &savedWorldToProjection]() {
                parserContext.GetProjectionDesc()._worldToProjection = savedWorldToProjection;
                parserContext.GetTechniqueContext()._runtimeState.SetParameter(StringShadowCascadeMode, 0);
            });

        CATCH_ASSETS_BEGIN
            parserContext.GetSceneParser()->ExecuteScene(
                context, parserContext, sceneParseSettings, 
                preparedScene, TechniqueIndex_RTShadowGen);
        CATCH_ASSETS_END(parserContext)

        metalContext.UnbindSO();
        Metal::GeometryShader::SetDefaultStreamOutputInitializers(oldSO);

            // We have the list of triangles. Let's render then into the final
            // grid buffer viewport. This should create a list of triangles for
            // each cell in the grid. The goal is to reduce the number of triangles
            // that the ray tracing shader needs to look at.
            //
            // We could attempt to do this in the same step above. But that creates
            // some problems with frustum cull and back face culling. This order
            // allows us reduce the total triangle count before we start assigning
            // primitive ids.
            //
            // todo -- also calculate min/max for each grid during this step
        CATCH_ASSETS_BEGIN
            auto& shader = ::Assets::GetAssetDep<Metal::ShaderProgram>(
                "game/xleres/shadowgen/rtwritetiles.sh:vs_passthrough:vs_*",
                "game/xleres/shadowgen/consraster.sh:gs_conservativeRasterization:gs_*",
                "game/xleres/shadowgen/rtwritetiles.sh:ps_main:ps_*",
                "OUTPUT_PRIM_ID=1;INPUT_RAYTEST_TRIS=1");
            metalContext.Bind(shader);

            Metal::BoundInputLayout inputLayout(Metal::InputLayout(il, dimof(il)), shader);
            metalContext.Bind(inputLayout);

                // no shader constants/resources required

            unsigned clearValues[] = { 0, 0, 0, 0 };
            metalContext.Clear(box._gridBufferUAV, clearValues);

            metalContext.Bind(Techniques::CommonResources()._blendOpaque);
            metalContext.Bind(Techniques::CommonResources()._dssDisable);
            metalContext.Bind(Techniques::CommonResources()._cullDisable);
            metalContext.Bind(Metal::Topology::PointList);
            metalContext.Bind(MakeResourceList(box._triangleBufferVB), strides[0], offsets[0]);

            metalContext.Bind(
                MakeResourceList(box._dummyRTV), nullptr,
                MakeResourceList(box._gridBufferUAV, box._listsBufferUAV));
            metalContext.DrawAuto();
        CATCH_ASSETS_END(parserContext)

        metalContext.Bind(Metal::Topology::TriangleList);
        savedTargets.ResetToOldTargets(metalContext);

        preparedResult._listHeadSRV = box._gridBufferSRV;
        preparedResult._linkedListsSRV = box._listsBufferSRV;
        preparedResult._trianglesSRV = box._triangleBufferSRV;
        return std::move(preparedResult);
    }