Example #1
0
    TextureDesc LoadTextureFormat(StringSection<::Assets::ResChar> filename)
    {
        ucs2 wfilename[MaxPath];
        Conversion::Convert(wfilename, dimof(wfilename), filename.begin(), filename.end());

        auto fmt = GetTexFmt(wfilename);
                
        using namespace DirectX;
        TexMetadata metadata;

        HRESULT hresult = -1;
        if (fmt == TexFmt::DDS) {
            hresult = GetMetadataFromDDSFile((const wchar_t*)wfilename, DDS_FLAGS_NONE, metadata);
        } else if (fmt == TexFmt::TGA) {
            hresult = GetMetadataFromTGAFile((const wchar_t*)wfilename, metadata);
        } else if (fmt == TexFmt::WIC) {
            hresult = GetMetadataFromWICFile((const wchar_t*)wfilename, WIC_FLAGS_NONE, metadata);
        } else {
            LogWarning << "Texture format not apparent from filename (" << filename.AsString().c_str() << ")";
        }

        if (SUCCEEDED(hresult)) {
            return BuildTextureDesc(metadata);
        }

        return TextureDesc::Empty();
    }
Example #2
0
void Execute(StringSection<char> cmdLine)
{
    // We're going to run a simple process that loads a texture file, runs some shader
    // process, and then writes out an output file.
    // This is a command line app; so our instructions should be on the command line.
    // We're going to use a stream formatter & our "Document" asbtraction to interpret
    // the command line.
    // We could replace the formatter with a version specialized for
    // command lines if we wanted a unix style command line syntax (and, actually, some
    // syntax elements of this formatter [like ';'] might conflict on some OSs.

    MemoryMappedInputStream stream(cmdLine.begin(), cmdLine.end());
    InputStreamFormatter<char> formatter(stream);
    Document<InputStreamFormatter<char>> doc(formatter);

    auto outputFile = doc.Attribute("o").Value();
    auto shader = doc.Attribute("s").Value();

    if (outputFile.Empty() || shader.Empty()) {
        return;
    }

    auto xleDir = GetEnv("XLE_DIR");
    if (xleDir.empty()) {
        LogAlwaysError << "XLE_DIR environment variable isn't set. Expecting this to be set to root XLE directory";
        LogAlwaysError << "This program loads shaders from the $(XLE_DIR)\\Working\\Game\\xleres folder";
        return;
    }

    // we can now construct basic services
    auto cleanup = MakeAutoCleanup([]() {
        TerminateFileSystemMonitoring();
    });
    auto device = RenderCore::CreateDevice();
    Samples::MinimalAssetServices services(device.get());

    // We need to think about SRGB modes... do we want to do the processing in
    // linear or SRGB space? So we want to write out a linear or SRB texture?
    auto shaderParameters = CreateParameterBox(doc.Element("p"));

    auto resultTexture = ExecuteTransform(
                             *device, MakeStringSection(xleDir), shader, shaderParameters,
    {
        { "Sky", HosekWilkieSky },
        { "Compress", CompressTexture }
    });
    if (!resultTexture._pkt) {
        LogAlwaysError << "Error while performing texture transform";
        return;
    }

    // save "readback" as an output texture.
    // We will write a uncompressed format; normally a second command line
    // tool will be used to compress the result.
    resultTexture.Save(outputFile.AsString().c_str());
}
Example #3
0
    std::shared_ptr<DependencyValidation> Store::WriteDependencies(
        const ResChar intermediateFileName[], 
        StringSection<ResChar> baseDir,
        IteratorRange<const DependentFileState*> deps,
        bool makeDepValidation) const
    {
        Data data;

        std::shared_ptr<DependencyValidation> result;
        if (makeDepValidation)
            result = std::make_shared<DependencyValidation>();

            //  we have to write the base directory to the dependencies file as well
            //  to keep it short, most filenames should be expressed as relative files
        char buffer[MaxPath];
        data.SetAttribute("BasePath", baseDir.AsString().c_str());

        SplitPath<ResChar> baseSplitPath(baseDir);

        auto dependenciesBlock = std::make_unique<Data>("Dependencies");
        for (auto& s:deps) {
            auto c = std::make_unique<Data>();

            auto relPath = MakeRelativePath(
                baseSplitPath, 
                SplitPath<ResChar>(s._filename));
            c->SetValue(relPath.c_str());

            if (s._status != DependentFileState::Status::Shadowed) {
                c->SetAttribute("ModTimeH", (int)(s._timeMarker>>32ull));
                c->SetAttribute("ModTimeL", (int)(s._timeMarker));
            }
            dependenciesBlock->Add(c.release());
            if (makeDepValidation) RegisterFileDependency(result, s._filename.c_str());
        }
Example #4
0
 void PushString(
     std::basic_streambuf<OutChar>& stream,
     StringSection<InChar> input)
 {
         //  String conversion process results in several redundant allocations. It's not perfectly
         //  efficient
     using OutputString = std::basic_string<OutChar>;
     auto converted = Conversion::Convert<OutputString>(input.AsString());
     stream.sputn(AsPointer(converted.begin()), converted.size());    
 }
Example #5
0
    void DirectorySearchRules::AddSearchDirectory(StringSection<ResChar> dir)
    {
            //  Attempt to fit this directory into our buffer.
            //  note that we have limited space in the buffer, but we can't really
            //  rely on all directory names remaining small and convenient... If we 
            //  overflow our fixed size buffer, we can use the dynamically 
            //  allocated "_bufferOverflow"
        assert((_startPointCount+1) <= dimof(_startOffsets));
        if ((_startPointCount+1) > dimof(_startOffsets)) {
                //  limited number of directories that can be pushed into a single "search rules"
                //  this allows us to avoid a little bit of awkward dynamic memory allocation
            return; 
        }

            // Check for duplicates
            //  Duplicates are bad because they will increase the number of search operations
        if (HasDirectory(dir)) return;

        unsigned allocationLength = (unsigned)(dir.Length() + 1);
        if (_bufferOverflow.empty() && (_bufferUsed + allocationLength <= dimof(_buffer))) {
                // just append this new string to our buffer, and add a new start offset
            XlCopyMemory(&_buffer[_bufferUsed], dir.begin(), (allocationLength-1) * sizeof(ResChar));
            _buffer[_bufferUsed+allocationLength-1] = '\0';
        } else {
            if (_bufferOverflow.empty()) {
                _bufferOverflow.resize(_bufferUsed + allocationLength);
                XlCopyMemory(AsPointer(_bufferOverflow.begin()), _buffer, _bufferUsed * sizeof(ResChar));
                XlCopyMemory(PtrAdd(AsPointer(_bufferOverflow.begin()), _bufferUsed * sizeof(ResChar)), dir.begin(), (allocationLength-1) * sizeof(ResChar));
                _bufferOverflow[_bufferUsed+allocationLength-1] = '\0';
            } else {
                assert(_bufferOverflow.size() == allocationLength);
                auto i = _bufferOverflow.insert(_bufferOverflow.end(), dir.begin(), dir.end());
                _bufferOverflow.insert(i + dir.Length(), 0);
            }
        }

        _startOffsets[_startPointCount++] = _bufferUsed;
        _bufferUsed += allocationLength;
    }
Example #6
0
 intrusive_ptr<DataPacket> CreateStreamingTextureSource(
     StringSection<::Assets::ResChar> filename, TextureLoadFlags::BitField flags)
 {
     return make_intrusive<StreamingTexture>(filename.begin(), filename.end(), flags);
 }
Example #7
0
    PreparedSkinFile::PreparedSkinFile(const ColladaScaffold& input, const VisualScene& scene, StringSection<utf8> rootNode)
    {
        using namespace RenderCore::ColladaConversion;

        SkeletonRegistry jointRefs;

        ReferencedGeometries refGeos;
        bool gatherSuccess = refGeos.Gather(scene.GetRootNode(), rootNode, jointRefs);

        if (!gatherSuccess) {
            StringMeld<1024> meld;
            using ::operator<<;
            meld << "Error while looking for root node: " << rootNode.AsString().c_str() << ". Known nodes: ";

            auto nodes = scene.GetRootNode().FindAllBreadthFirst([](const Node& n) { return true;});
            for (unsigned c=0; c<nodes.size(); ++c) {
                if (c!=0) meld << ", ";
                meld << nodes[c].GetName().AsString().c_str();
            }

            Throw(::Assets::Exceptions::FormatError(meld.get()));
        }

            // The skeleton joints won't be included in the skeleton
            // until we call FindSkinJoints. We don't really need the
            // full skeleton embedded in the skin file... When the skeleton
            // is not there, we will just see the model in the bind pose.
            // But it can be handy to be there for previewing models quickly.
        refGeos.FindSkinJoints(scene, input._resolveContext, jointRefs);

            // We can now build the skeleton (because ReferencedGeometries::Gather 
            // has initialised jointRefs.

        unsigned topLevelPops = 0;
        auto coordinateTransform = BuildCoordinateTransform(input._doc->GetAssetDesc());
        if (!Equivalent(coordinateTransform, Identity<Float4x4>(), 1e-5f)) {
                // Push on the coordinate transform (if there is one)
                // This should be optimised into other matrices (or even into
                // the geometry) when we perform the skeleton optimisation steps.
            topLevelPops = _skeleton.GetTransformationMachine().PushTransformation(
                coordinateTransform);
        }

            // When extracting an internal node, we ignore the transform 
            // on that internal node
        BuildSkeleton(_skeleton, scene.GetRootNode(), rootNode, jointRefs, false);
        _skeleton.GetTransformationMachine().Pop(topLevelPops);

            // For each output matrix, we want to know if we can merge a transformation into it.
            // We can only do this if (unskinned) geometry instances are attached -- and those
            // geometry instances must be attached in only one place. If the output transform does
            // not have a geometry instance attached, or if any of the geometry instances are
            // attached to more than one matrix, or if something other than a geometry instance is
            // attached, then we cannot do any merging.
        
        TransMachineOptimizer optimizer(refGeos, _skeleton.GetTransformationMachine().GetOutputMatrixCount(), scene);
        _skeleton.GetTransformationMachine().Optimize(optimizer);

            // We can try to optimise the skeleton here. We should collect the list
            // of meshes that we can optimise transforms into (ie, meshes that aren't
            // used in multiple places, and that aren't skinned).
            // We need to collect that list of transforms before we actually instantiate
            // the geometry -- so that merging in the changes can be done in the instantiate
            // step.

        for (auto c:refGeos._meshes) {
            TRY {
                _cmdStream.Add(
                    RenderCore::ColladaConversion::InstantiateGeometry(
                        scene.GetInstanceGeometry(c._objectIndex),
                        c._outputMatrixIndex, optimizer.GetMergedOutputMatrix(c._outputMatrixIndex),
                        c._levelOfDetail,
                        input._resolveContext, _geoObjects, jointRefs,
                        input._cfg));
            } CATCH(const std::exception& e) {
                LogWarning << "Got exception while instantiating geometry (" << scene.GetInstanceGeometry(c._objectIndex)._reference.AsString().c_str() << "). Exception details:";
                LogWarning << e.what();
            } CATCH(...) {
                LogWarning << "Got unknown exception while instantiating geometry (" << scene.GetInstanceGeometry(c._objectIndex)._reference.AsString().c_str() << ").";
            } CATCH_END
Example #8
0
 void PushString(
     std::basic_streambuf<OutChar>& stream,
     StringSection<InChar> input)
 {
     stream.sputn((const OutChar*)input.begin(), input.Length());
 }
Example #9
0
void FileOutputStream::Write(StringSection<ucs4> s)
{
    _file.Write(s.begin(), sizeof(*s.begin()), s.Length());
}