Форум программистов, компьютерный форум, киберфорум
Наши страницы

Пишу игровой движок на C++. 017. Загрузка плагина, инициализация Direct 3D 11

Войти
Регистрация
Восстановить пароль
Сайт движка - gost.imsoftworks.info
Исходные коды движка - https://github.com/532235/GoST
Документация
Примеры кода программ - https://github.com/532235/GoST/wiki

Другой хобби-проект в группе в вк https://vk.com/club154291467
Оценить эту запись

Пишу игровой движок на C++. 017. Загрузка плагина, инициализация Direct 3D 11

Запись от 532235 размещена 11.12.2017 в 15:07

Думаю это будет тяжёлым для понимания пост.
Загрузка и инизиализация плагина потребует некоторых усилий.

Нужно просканировать папку с плагинами.
Найти нужный.
Загрузить его, сохранив всю информацию чтобы потом автоматически всё выгрузилось.
Инициализировать то что он должен инициализировать.


Ранее хотел делать старый d3d рендер.
Мне лично без разницы на каком делать, буду делать на 11, ибо это будет наиболее интересно для читателя.

Все комментарии будут в коде

gtPluginSystem.h
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
#pragma once
#ifndef __GT_PLUGIN_SYSTEM_H__
#define __GT_PLUGIN_SYSTEM_H__
 
 
/*
*/
 
namespace gost{
    
    class gtMainSystem;
 
        //  тип плагина
    enum class gtPluginType{
 
        //  плагины должны быть правильно инициализированы
        unknown,
 
        //  рендер
        render,
 
        //  импортёр картинок
        import_image,
 
        //  импортёр моделей
        import_model
 
        // для начала хватит
    };
 
        //  общая информация о плагине
    struct gtPluginInfo{
        gtPluginInfo( void ):
            m_type( gtPluginType::unknown )
        {
                //  нельзя выделять память в одном модуле и освобождать в другом
                //  выход за пределы - на совести разработчика плагина
            m_name.reserve( 64u );
            m_author.reserve( 64u );
            m_url.reserve( 64u );
            m_email.reserve( 64u );
            m_company.reserve( 64u );
            m_description.reserve( 512u );
            m_GUID.reserve( 64u );
        }
 
        //  тип плагина
        gtPluginType m_type;
 
        //  название плагина
        gtString m_name;
 
        //  автор
        gtString m_author;
 
        //  ссылка на сайт
        gtString m_url;
 
        //  контактный имейл
        gtString m_email;
 
        //  имя компании если юр лицо
        gtString m_company;
 
        //  описание
        gtString m_description;
 
        //  уникальный ID. по сути любая строка.
        //  имя по аналогии с GUID. {41B20362-9FC0-4C40-9903-B8D2FF98CF88}
        gtString m_GUID;
 
    };
 
    //  указывается при создании gtDriver
    const gtString GT_GUID_RENDER_D3D11( u"{41B20362-9FC0-4C40-9903-B8D2FF98CF88}" );
 
    //  для загрузки функций из плагинов
    using gtGetPluginInfo = void(*)(gtPluginInfo&);
    using gtLoadGPUDriver_t = gtDriver*(*)(gtMainSystem*,gtDriverInfo);
 
        //  Интерфейс для работы с плагинами
    class gtPluginSystem : public gtRefObject{
    public:
 
            //  получить количество плагинов в папке plugins
        virtual u32 getNumOfPlugins( void ) = 0;
 
 
    };
 
}
 
#endif
"{41B20362-9FC0-4C40-9903-B8D2FF98CF88}"
…почему данный формат (GUID) - всего навсего уникальный код, в Visual Studio генерация автоматическая

gtPluginSystemImpl.h
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
#pragma once
#ifndef __GT_PLUGIN_SYSTEM_IMPL_H__
#define __GT_PLUGIN_SYSTEM_IMPL_H__
 
namespace gost{
 
    /*  Информация о плагине. Содержит путь к файлу
        указатель на фукнцию запуска,
        хэндл,
        так же общая информация gtPluginInfo*/
    struct gtPluginInfoDL{
 
        gtPluginInfoDL( void ):
            m_loadPlugin( nullptr ),
            m_handle( nullptr )
        {}
 
        ~gtPluginInfoDL( void ){}
 
        //  путь к файлу
        gtString m_path;
 
        //  указатель на функцию записи
        void (*m_loadPlugin)();
        
        //  handle плагина
        GT_LIBRARY_HANDLE m_handle;
 
        //  общая информация
        gtPluginInfo m_info;
    };
 
    /*
        Это обёртка к render плагину.
        Хранит информацию.
        Благодоря этому можно грузить и выгружать плагин 
        используя методы load unload
    */
    class gtPluginRender : public gtRefObject{
 
            //  загружен ли плагин
        bool m_isLoad;
 
            //  информация
        gtPluginInfoDL  m_info;
 
    public:
 
        gtPluginRender( gtPluginInfoDL* info ):
            m_isLoad( false )
        {
            m_info = *info;
        }
 
        ~gtPluginRender( void ){
            unload();
        }
 
            //  видео драйвер
        gtPtr<gtDriver> m_driver;
 
            //  загрузить плагин
        void load( const gtDriverInfo& params );
 
            //  выгрузитьплагин
        void unload( void );
 
    };
 
    class gtPluginSystemImpl GT_FINAL : public gtPluginSystem{
 
        void scanFolder( const gtString& );
 
        u32 m_numOfPlugins;
 
        //  доступные для загрузки
        gtArray<gtPluginInfoDL> m_renderPluginCache;
        
        //  загруженные плагины
        gtList<gtPluginRender*> m_renderPlugins;
 
    public:
        gtPluginSystemImpl( void );
        virtual ~gtPluginSystemImpl( void );
 
        bool init( void );
 
            //  получить количество плагинов в папке plugins
        u32 getNumOfPlugins( void );
 
            //  загружает видео плагин
        gtDriver*   loadRenderPlugin( const gtDriverInfo& params );
 
            //  выгружает и удаляет из коллекции
        void        unloadRenderPlugin( gtDriver* );
 
    };
 
}
 
#endif
Как будет производиться запуск...
Нужно заполнить структуру
- gtDriverInfo
Вызвать метод для загрузки плагина - метод из главной системы, возвращающий указатель на новый абстрактный тип.

создам новый .h файл

gtDriver.h
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
#pragma once
#ifndef __GT_DRIVER_H__
#define __GT_DRIVER_H__
 
/*
*/
 
namespace gost{
 
    class gtWindow;
 
 
        //  параметры запуска драйвера
    struct gtDriverInfo{
 
        gtDriverInfo( void ):
            m_GUID(u"-"),
            m_fullScreen( false ),
            m_stencilBuffer( true ),
            m_doubleBuffer( true ),
            m_vSync( false ),
            m_colorDepth( 32u ),
            m_adapterID( 0u ),
            m_outWindow( nullptr )
        {
            m_backBufferSize.set({800,600});
        }
 
            //  ID драйвера
        gtString m_GUID;
 
            //  разрешение экрана
        v2i     m_backBufferSize;
 
            //  запускать ли программу в полноэкранном режиме
        bool    m_fullScreen;
 
            //  использовать ли стенсильный буффер. Нужен для OGL, в D3D по умолчанию есть.
        bool    m_stencilBuffer;
 
            //  двойная буферизация
        bool    m_doubleBuffer;
 
            //  вертикльная синхронизация
        bool    m_vSync;
 
            //  глубина цвета - биты на пиксель
        u8      m_colorDepth;
 
            // only for Direct3D
        u32     m_adapterID;
 
            //  окно для рисования
        gtWindow * m_outWindow;
    };
 
        //  видео драйвер
    class gtDriver : public gtRefObject{
    public:
 
            //  получить параметры
        virtual const gtDriverInfo& getParams( void ) = 0;
            
            //  
        virtual void beginRender( bool clearRenderTarget = true, const gtColor& color = gtColor(0.f) ) = 0;
        virtual void endRender( void ) = 0;
 
        virtual void *  getPluginHandle( void ) = 0;
    };
 
        //  реализация драйвера в отдельных dll
        //  по этому создавать общий класс вижу только таким способом
    class gtDriverCommon : public gtDriver{
 
    protected:
 
            //  параметры запуска
        gtDriverInfo m_params;
            
            /*временно*/
        void * m_handle;
 
    public:
 
        gtDriverCommon( void ):
            m_handle(nullptr)
        {
        }
 
        virtual ~gtDriverCommon( void ){
        }
 
 
            //  получить параметры
        virtual const gtDriverInfo& getParams( void ){
            return m_params;
        }
 
        virtual void *  getPluginHandle( void ){
            return m_handle;
        }
 
        /*временно*/
        friend void setHandle( gtDriver* instance, void * h );
    };
 
    /*временно*//*возможно уберу*/
    GT_FORCE_INLINE void setHandle( gtDriver* instance, void * h ){
        ((gtDriverCommon*)instance)->m_handle = h;
    }
 
}
 
#endif
В класс gtMainSystem добавляю новые методы
C++
1
2
3
4
5
6
7
    //  Инициализирует видео драйвер
virtual gtDriver*   createVideoDriver( const gtDriverInfo& ) = 0;
    //  Завершает работу видео драйвера, выгружает .dll и удаляет из коллекции
    //  возможно и не нужно.
    //  можно вызвать driver->release();
    //  но библиотека будетвсё ещё загружена. По этому есть эта функция.
virtual void        removeVideoDriver( gtDriver** ) = 0;
Нужно подумать над реализацией createVideoDriver
Вроде нет ничего зависимого от ОС.
Что нужно делать в этом методе.

Проверить, есть ли у какого-либо графического плагина такой же id
Загрузить библиотеку.
Инициализировать и вернуть указатель.

Для того, чтобы проверять id плагина, нужно создать контейнер который хранит информацию об имеющихся плагинах.
При сканировании папки заносить в него всю информацию.
Плюс дополнительную -
gtPluginInfoDL

в gtPluginSystemImpl будет массив для хранения информации о render плагинах
C++
1
gtArray<gtPluginInfoDL> m_renderPluginCache;
Теперь сканирование папки. Если есть все нужные процедуры то в кеш добавляется информация.
Потом можно будет грузить плагин.

Так же чтобы отделять release от debug версий, у debug плагина будет расширение .gpld

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
void gtPluginSystemImpl::scanFolder( const gtString& dir ){
    gtArray<gtFileSystem::DirObject> objs;
 
    gtFileSystem::scanDirBegin( dir );
    gtFileSystem::DirObject dob;
    while( gtFileSystem::getDirObject( &dob ) ){
        objs.push_back( dob );
    }
    gtFileSystem::scanDirEnd();
 
    u32 sz = objs.size();
 
    for( u32 i = 0u; i < sz; ++i ){
        auto * o = &objs[ i ];
        if( o->type == gtFileSystem::DirObjectType::file ){
            gtString extension = util::stringGetExtension<gtString>( gtString((char16_t*)o->path) );
            if( extension == u"gpl" || extension == u"gpld" ){
                 
#ifdef GT_DEBUG
                if( extension.size() == 3 ) continue;
#else
                if( extension.size() == 4 ) continue;
#endif
 
 
                gtPluginInfoDL pi_dl;
 
                GT_LIBRARY_HANDLE lib = GT_LOAD_LIBRARY(o->path);
                if( !lib ){
                    gtLogWriter::printWarning( u"Can not load plugin [%s]", o->path );
                    continue;
                }
 
                gtGetPluginInfo f_GetPluginInfo = (gtGetPluginInfo)GT_LOAD_FUNCTION( lib, "GetPluginInfo" );
                if( !f_GetPluginInfo ){
                    gtLogWriter::printWarning( u"Can not get procedure address [%s] from plugin [%s]", u"GetPluginInfo", o->path );
                    GT_FREE_LIBRARY( lib );
                    continue;
                }
 
                gtPluginInfo pi;
                f_GetPluginInfo( pi );
                
                //  пока добавляется только общая информация
                pi_dl.m_path.assign((char16_t*)o->path);
                pi_dl.m_info = pi;
                
                if( pi.m_type == gtPluginType::unknown ){
                    gtLogWriter::printWarning( u"Unsupported plugin [%s]", o->path );
                }else if( pi.m_type == gtPluginType::render ){
                    m_numOfPlugins++;
 
                    gtLoadGPUDriver_t gtLoadGPUDriver =     (gtLoadGPUDriver_t)GT_LOAD_FUNCTION(lib,"gtLoadGPUDriver");
                    if( !gtLoadGPUDriver ){
                        gtLogWriter::printWarning( u"Can not get procedure address [%s] from plugin [%s]", u"gtLoadGPUDriver", o->path );
                        GT_FREE_LIBRARY( lib );
                        continue;
                    }
                                        
                    this->m_renderPluginCache.push_back( pi_dl );
                }
 
 
                GT_FREE_LIBRARY( lib );
 
            }
        }
    }
 
    for( u32 i = 0u; i < sz; ++i ){
        auto * o = &objs[ i ];
 
        if( o->type == gtFileSystem::DirObjectType::folder ){
            scanFolder( (char16_t*)o->path );
        }
    }
}

Теперь нужно загрузить плагин.
Нужно реализовать метод
createVideoDriver
Реализация в gtMainSystemCommon
C++
1
2
3
4
5
6
7
8
9
    //  Инициализирует видео драйвер
gtDriver* gtMainSystemCommon::createVideoDriver( const gtDriverInfo& params ){
    return m_pluginSystem->loadRenderPlugin( params );
}
    //  Завершает работу видео драйвера
void gtMainSystemCommon::removeVideoDriver( gtDriver** pDriver ){
    m_pluginSystem->unloadRenderPlugin( *pDriver );
    *pDriver = nullptr;
}
функции загрузки и выгрузки
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
gtPluginSystemImpl::gtPluginSystemImpl( void ):
    m_numOfPlugins( 0u )
{
}
 
 
gtPluginSystemImpl::~gtPluginSystemImpl( void ){
    for each ( auto var in m_renderPluginCache ){
        if( var.m_handle ){
            GT_FREE_LIBRARY( var.m_handle );
        }
    }
    m_renderPluginCache.clear();
}
 
 
void gtPluginSystemImpl::scanFolder( const gtString& dir ){
    gtArray<gtFileSystem::DirObject> objs;
 
    gtFileSystem::scanDirBegin( dir );
    gtFileSystem::DirObject dob;
    while( gtFileSystem::getDirObject( &dob ) ){
        objs.push_back( dob );
    }
    gtFileSystem::scanDirEnd();
 
    u32 sz = objs.size();
 
    for( u32 i = 0u; i < sz; ++i ){
        auto * o = &objs[ i ];
        if( o->type == gtFileSystem::DirObjectType::file ){
            gtString extension = util::stringGetExtension<gtString>( gtString((char16_t*)o->path) );
            if( extension == u"gpl" || extension == u"gpld" ){
                 
#ifdef GT_DEBUG
                if( extension.size() == 3 ) continue;
#else
                if( extension.size() == 4 ) continue;
#endif
 
 
                gtPluginInfoDL pi_dl;
 
                GT_LIBRARY_HANDLE lib = GT_LOAD_LIBRARY(o->path);
                if( !lib ){
                    gtLogWriter::printWarning( u"Can not load plugin [%s]", o->path );
                    continue;
                }
 
                gtGetPluginInfo f_GetPluginInfo = (gtGetPluginInfo)GT_LOAD_FUNCTION( lib, "GetPluginInfo" );
                if( !f_GetPluginInfo ){
                    gtLogWriter::printWarning( u"Can not get procedure address [%s] from plugin [%s]", u"GetPluginInfo", o->path );
                    GT_FREE_LIBRARY( lib );
                    continue;
                }
 
                gtPluginInfo pi;
                f_GetPluginInfo( pi );
                
                //  пока добавляется только общая информация
                pi_dl.m_path.assign((char16_t*)o->path);
                pi_dl.m_info = pi;
                
                if( pi.m_type == gtPluginType::unknown ){
                    gtLogWriter::printWarning( u"Unsupported plugin [%s]", o->path );
                }else if( pi.m_type == gtPluginType::render ){
                    m_numOfPlugins++;
 
                    gtLoadGPUDriver_t gtLoadGPUDriver =     (gtLoadGPUDriver_t)GT_LOAD_FUNCTION(lib,"gtLoadGPUDriver");
                    if( !gtLoadGPUDriver ){
                        gtLogWriter::printWarning( u"Can not get procedure address [%s] from plugin [%s]", u"gtLoadGPUDriver", o->path );
                        GT_FREE_LIBRARY( lib );
                        continue;
                    }
                                        
                    this->m_renderPluginCache.push_back( pi_dl );
                }
 
 
                GT_FREE_LIBRARY( lib );
 
            }
        }
    }
 
    for( u32 i = 0u; i < sz; ++i ){
        auto * o = &objs[ i ];
 
        if( o->type == gtFileSystem::DirObjectType::folder ){
            scanFolder( (char16_t*)o->path );
        }
    }
}
 
bool gtPluginSystemImpl::init( void ){
 
    gtString pluginsDir( gtFileSystem::getProgramPath() + u"plugins/" );
 
    if( !gtFileSystem::existDir( pluginsDir ) ){
        gtLogWriter::printError( u"Plugins folder not found" );
        return false;
    }
 
    scanFolder( pluginsDir );
 
    return true;
}
 
    //  получить количество плагинов в папке plugins
u32 gtPluginSystemImpl::getNumOfPlugins( void ){
    return m_numOfPlugins;
}
 
gtDriver*   gtPluginSystemImpl::loadRenderPlugin( const gtDriverInfo& params ){
    gtDriver* ret(nullptr);
 
    u32 sz = m_renderPluginCache.size();
 
    if( !sz ){
        gtLogWriter::printError( u"Can not load render plugin [%s]. No plugin.", params.m_GUID.data() );
        return ret;
    }
 
    for( u32 i = 0u; i < sz; ++i ){
        auto * o = &m_renderPluginCache[ i ];
        if( o->m_info.m_GUID == params.m_GUID ){
 
            gtPtr<gtPluginRender> render = gtPtrNew<gtPluginRender>( new gtPluginRender( o ) );
            render->load( params );
 
            ret = render->m_driver.data();
 
            m_renderPlugins.add( render.data() );
            render->addRef();
 
            break;
        }
    }
    
    
    return ret;
}
 
void gtPluginSystemImpl::unloadRenderPlugin( gtDriver* d ){
    u32 sz = m_renderPlugins.size();
 
    for( u32 i = 0u; i < sz; ++i ){
        auto  o = m_renderPlugins.get( i );
 
        if( o->m_driver.data() == d ){
            m_renderPlugins.remove( o );
            o->unload();
            delete o;
            break;
        }
 
    }
}
 
void gtPluginRender::load( const gtDriverInfo& params ){
    if( !m_isLoad ){
 
        if( m_info.m_handle )
            GT_FREE_LIBRARY( m_info.m_handle );
 
        m_info.m_handle =   GT_LOAD_LIBRARY( (wchar_t*)m_info.m_path.data() );
 
        if( !m_info.m_handle ){
            gtLogWriter::printWarning( u"Can not load plugin [%s]", m_info.m_path.data() );
            return;
        }
 
        gtLoadGPUDriver_t loadProc = (gtLoadGPUDriver_t)GT_LOAD_FUNCTION( m_info.m_handle, "gtLoadGPUDriver" );
        if( !loadProc ){
            gtLogWriter::printWarning( u"Can not get procedure address [%s] from plugin [%s]", u"gtLoadGPUDriver", m_info.m_path.data() );
            GT_FREE_LIBRARY( m_info.m_handle );
            return;
        }
                
        m_info.m_loadPlugin = (void(*)())loadProc;
 
        m_driver = gtPtrNew<gtDriver>( ((gtLoadGPUDriver_t)m_info.m_loadPlugin)( gtMainSystemCommon::getInstance(), params ) );
 
        if( m_driver.data() ){
        //  setHandle( m_driver.data(), m_info.m_handle );
            m_isLoad = true;
 
        }else{
            GT_FREE_LIBRARY( m_info.m_handle );
        }
    }
}
 
void gtPluginRender::unload( void ){
    if( m_isLoad ){
 
        if( m_driver.data() )
            m_driver->release();
 
        GT_FREE_LIBRARY( m_info.m_handle );
        m_info.m_handle = nullptr;
 
        m_isLoad = false;
    }
}
Теперь создам сам плагин - новый проект - DLL
имя gtD3D11
в gtD3D11.cpp нужно добавить

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include "stdafx.h"
 
#ifdef _DEBUG
#pragma comment(lib, "gost_d.lib")
#else 
#pragma comment(lib, "gost.lib")
#endif
 
extern "C"{
 
    __declspec(dllexport) void  GetPluginInfo( gtPluginInfo& info ){
        info.m_author.assign( u"532235" );
        info.m_description.assign( u"Direct3D 11 renderer" );
        info.m_GUID.assign( GT_GUID_RENDER_D3D11 );
        info.m_name.assign( u"Direct3D 11 renderer" );
        info.m_type = gtPluginType::render;
    }
 
    __declspec(dllexport) gtDriver * gtLoadGPUDriver( gtMainSystem* System, gtDriverInfo params ){
 
        gtLogWriter::printInfo( u"Init D3D11 driver..." );
 
        gtPtr<gtDriverD3D11>     driver = gtPtrNew<gtDriverD3D11>(new gtDriverD3D11( System, params ));
 
        if( driver.data() ){
            
            if( driver->initialize())
                driver->addRef();
            else{
                driver->release();
                gtLogWriter::printError( u"Can not initialize D3D11 driver." );
                return nullptr;
            }
        }
 
        return driver.data();
    }
}
Создаю реализацию gtDriverCommon для Direct3D 11
gtDriverD3D11.h
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#pragma once
 
#ifndef __GT_DRIVER_D3D11_H__
#define __GT_DRIVER_D3D11_H__
 
using gtD3D11CreateDevice_t = HRESULT(__stdcall*)(_In_opt_ IDXGIAdapter* pAdapter,D3D_DRIVER_TYPE DriverType,HMODULE Software,UINT Flags,_In_reads_opt_( FeatureLevels ) CONST D3D_FEATURE_LEVEL* pFeatureLevels,UINT FeatureLevels,UINT SDKVersion,_Out_opt_ ID3D11Device** ppDevice,_Out_opt_ D3D_FEATURE_LEVEL* pFeatureLevel,_Out_opt_ ID3D11DeviceContext** ppImmediateContext);
using gtD3D11CreateDeviceAndSwapChain_t = HRESULT(__stdcall*)(__in_opt IDXGIAdapter* pAdapter,D3D_DRIVER_TYPE DriverType,HMODULE Software,UINT Flags,__in_ecount_opt( FeatureLevels ) CONST D3D_FEATURE_LEVEL* pFeatureLevels,UINT FeatureLevels,UINT SDKVersion,__in_opt CONST DXGI_SWAP_CHAIN_DESC* pSwapChainDesc,__out_opt IDXGISwapChain** ppSwapChain,__out_opt ID3D11Device** ppDevice,__out_opt D3D_FEATURE_LEVEL* pFeatureLevel,__out_opt ID3D11DeviceContext** ppImmediateContext );
 
namespace gost{
 
    class gtDriverD3D11 GT_FINAL : public gtDriverCommon{
 
        gtMainSystem* m_system;
 
        HMODULE m_D3DLibrary;
 
        IDXGISwapChain*         m_SwapChain;
        ID3D11Device*           m_d3d11Device;
        ID3D11DeviceContext*    m_d3d11DevCon;
        ID3D11RenderTargetView* m_MainTargetView;
        ID3D11Texture2D*        m_depthStencilBuffer;
        ID3D11DepthStencilState*m_depthStencilStateEnabled;
        ID3D11DepthStencilState*m_depthStencilStateDisabled;
        D3D11_DEPTH_STENCIL_VIEW_DESC   m_depthStencilViewDesc;
        ID3D11DepthStencilView* m_depthStencilView;
        ID3D11RasterizerState*  m_RasterizerSolid;
        ID3D11RasterizerState*  m_RasterizerSolidNoBackFaceCulling;
        ID3D11RasterizerState*  m_RasterizerWireframe;
        ID3D11RasterizerState*  m_RasterizerWireframeNoBackFaceCulling;
 
        void clearRenderTarget( const gtColor& );
 
        bool m_beginRender;
 
    public:
        gtDriverD3D11( gtMainSystem* System, gtDriverInfo params );
        ~gtDriverD3D11( void );
        bool initialize( void );
 
 
 
        const gtDriverInfo& getParams( void ) const;
            //  
        void beginRender( bool clearRenderTarget = true, const gtColor& color = gtColor(0.f) );
        void endRender( void );
    };
 
}
 
#endif
gtDriverD3D11.cpp
пусть всё будет пока так…
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
#include "stdafx.h"
 
gtDriverD3D11::gtDriverD3D11( gtMainSystem* System, gtDriverInfo params ):
    m_beginRender( false ),
    m_system( System ),
    m_D3DLibrary( nullptr ),
    m_SwapChain( nullptr ),
    m_d3d11Device( nullptr ),
    m_d3d11DevCon( nullptr ),
    m_MainTargetView( nullptr ),
    m_depthStencilBuffer( nullptr ),
    m_depthStencilStateEnabled( nullptr ),
    m_depthStencilStateDisabled( nullptr ),
    m_depthStencilView( nullptr ),
    m_RasterizerSolid( nullptr ),
    m_RasterizerSolidNoBackFaceCulling( nullptr ),
    m_RasterizerWireframe( nullptr ),
    m_RasterizerWireframeNoBackFaceCulling( nullptr )
{
    m_params =  params;
}
 
 
gtDriverD3D11::~gtDriverD3D11( void ){
 
    if( m_RasterizerWireframeNoBackFaceCulling )
        m_RasterizerWireframeNoBackFaceCulling->Release();
 
    if( m_RasterizerWireframe )
        m_RasterizerWireframe->Release();
 
    if( m_RasterizerSolidNoBackFaceCulling )
        m_RasterizerSolidNoBackFaceCulling->Release();
 
    if( m_RasterizerSolid )
        m_RasterizerSolid->Release();
 
    if( m_depthStencilView )
        m_depthStencilView->Release();
 
    if( m_depthStencilStateDisabled )
        m_depthStencilStateDisabled->Release();
 
    if( m_depthStencilStateEnabled )
        m_depthStencilStateEnabled->Release();
 
    if( m_depthStencilBuffer )
        m_depthStencilBuffer->Release();
 
    if( m_MainTargetView )
        m_MainTargetView->Release();
 
    if( m_d3d11DevCon )
        m_d3d11DevCon->Release();
 
    if( m_d3d11Device )
        m_d3d11Device->Release();
 
    if( m_SwapChain )
        m_SwapChain->Release();
 
    if( m_D3DLibrary )
        FreeLibrary( m_D3DLibrary );
}
 
 
const gtDriverInfo& gtDriverD3D11::getParams( void ) const {
        return  m_params;
}
 
bool gtDriverD3D11::initialize( void ){
 
    if( !m_params.m_outWindow ){
        gtLogWriter::printError( u"No render out window." );
        return false;
    }
 
    HWND outWindow = (HWND)m_params.m_outWindow->getHandle();
 
    //  Describes a display mode.
    DXGI_MODE_DESC  bufferDesc;
    ZeroMemory( &bufferDesc, sizeof(bufferDesc) );
    //  A value that describes the resolution width
    bufferDesc.Width    =   m_params.m_backBufferSize[0u];
    //  A value describing the resolution height
    bufferDesc.Height   =   m_params.m_backBufferSize[1u];
    //  refresh rate in hertz
    if( m_params.m_vSync )
        bufferDesc.RefreshRate.Numerator    =   60;
    else bufferDesc.RefreshRate.Numerator   =   0;
    bufferDesc.RefreshRate.Denominator  =   1;
    //  display format
    bufferDesc.Format   =   DXGI_FORMAT_R8G8B8A8_UNORM;
    bufferDesc.ScanlineOrdering =   DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
    bufferDesc.Scaling  =   DXGI_MODE_SCALING_UNSPECIFIED;
    
    DXGI_SWAP_CHAIN_DESC    swapChainDesc;
    ZeroMemory( &swapChainDesc, sizeof(swapChainDesc) );
    swapChainDesc.BufferDesc    =   bufferDesc;
    swapChainDesc.BufferUsage   =   DXGI_USAGE_RENDER_TARGET_OUTPUT;
    swapChainDesc.OutputWindow  =   outWindow;
    swapChainDesc.SampleDesc.Count  =   1;
    swapChainDesc.SampleDesc.Quality    =   0;
    swapChainDesc.BufferCount   =   1;
    swapChainDesc.Windowed  =   true;
    swapChainDesc.SwapEffect    =   DXGI_SWAP_EFFECT_DISCARD;
    swapChainDesc.Flags =   0;
 
    gtString d3dlib_str = gtFileSystem::getSystemPath();
    d3dlib_str += u"d3d11.dll";
 
    m_D3DLibrary = LoadLibrary( (wchar_t*)d3dlib_str.data() );
    if( !m_D3DLibrary ){
        gtLogWriter::printError( u"Could not load d3d11.dll" );
        return false;
    }
 
    gtD3D11CreateDevice_t D3D11CreateDevice = (gtD3D11CreateDevice_t)GetProcAddress(m_D3DLibrary, "D3D11CreateDevice");
    if( !D3D11CreateDevice ){
        gtLogWriter::printError( u"Could not get proc adress of D3D11CreateDevice");
        return false;
    }
 
    gtD3D11CreateDeviceAndSwapChain_t D3D11CreateDeviceAndSwapChain =
        (gtD3D11CreateDeviceAndSwapChain_t)GetProcAddress(m_D3DLibrary, "D3D11CreateDeviceAndSwapChain");
    if( !D3D11CreateDeviceAndSwapChain ){
        gtLogWriter::printError( u"Could not get proc adress of D3D11CreateDeviceAndSwapChain");
        return false;
    }
 
    D3D_FEATURE_LEVEL FeatureLevels[] = {
    D3D_FEATURE_LEVEL_11_1,
    D3D_FEATURE_LEVEL_11_0,
    D3D_FEATURE_LEVEL_10_1,
    D3D_FEATURE_LEVEL_10_0,
    D3D_FEATURE_LEVEL_9_3,
    D3D_FEATURE_LEVEL_9_2,
    D3D_FEATURE_LEVEL_9_1
    };
    D3D_FEATURE_LEVEL featureLevel = D3D_FEATURE_LEVEL_11_1;
    if( FAILED(D3D11CreateDevice(
        nullptr,
        D3D_DRIVER_TYPE_HARDWARE,
        nullptr,
        0,
        &FeatureLevels[0],
        ARRAYSIZE( FeatureLevels ),
        D3D11_SDK_VERSION,
        nullptr,
        &featureLevel,
        nullptr ))){
            gtLogWriter::printError( u"Can not get D3D Feature Level");
        return false;
    }
 
    if( featureLevel == D3D_FEATURE_LEVEL_11_0 ){
        gtLogWriter::printInfo( u"D3D feature level 11.0" );
    }else if( featureLevel == D3D_FEATURE_LEVEL_11_1 ){
        gtLogWriter::printInfo( u"D3D feature level 11.1" );
    }
 
    if( FAILED( D3D11CreateDeviceAndSwapChain( 
        nullptr,
        D3D_DRIVER_TYPE_HARDWARE, 
        nullptr,
        0, 
        &featureLevel, 
        1,
        D3D11_SDK_VERSION, 
        &swapChainDesc,
        &m_SwapChain,
        &m_d3d11Device, 
        nullptr, 
        &m_d3d11DevCon ) ) ){
            gtLogWriter::printError( u"Can't create Direct3D 11 Device" );
        return false;
    }
 
    ID3D11Texture2D* BackBuffer;
    if( FAILED( m_SwapChain->GetBuffer( 
        0,
        __uuidof( ID3D11Texture2D ), 
        (void**)&BackBuffer ) ) ){
        gtLogWriter::printError( u"Can't create Direct3D 11 back buffer" );
        return false;
    }
 
 
    if( FAILED( this->m_d3d11Device->CreateRenderTargetView( 
        BackBuffer, 0, &m_MainTargetView ) ) ){
        gtLogWriter::printError( u"Can't create Direct3D 11 render target" );
        if( BackBuffer ) BackBuffer->Release();
        return false;
    }
    
    if( BackBuffer ) BackBuffer->Release();
 
    D3D11_TEXTURE2D_DESC    DSD;
    ZeroMemory( &DSD, sizeof(DSD) );
    DSD.Width   =   m_params.m_backBufferSize[0u];
    DSD.Height  =   m_params.m_backBufferSize[1u];
    DSD.MipLevels   =   1;
    DSD.ArraySize   =   1;
    DSD.Format  =   DXGI_FORMAT_D32_FLOAT;
    DSD.SampleDesc.Count    =   1;
    DSD.SampleDesc.Quality  =   0;
    DSD.Usage   =   D3D11_USAGE_DEFAULT;
    DSD.BindFlags   =   D3D11_BIND_DEPTH_STENCIL;
    DSD.CPUAccessFlags  =   0;
    DSD.MiscFlags   =   0;
    if( FAILED( m_d3d11Device->CreateTexture2D( &DSD, 0, &m_depthStencilBuffer ) ) ){
        gtLogWriter::printError( u"Can't create Direct3D 11 depth stencil buffer" );
        return false;
    }
 
    D3D11_DEPTH_STENCIL_DESC    depthStencilDesc;
    ZeroMemory( &depthStencilDesc, sizeof(depthStencilDesc) );
    depthStencilDesc.DepthEnable    =   true;
    depthStencilDesc.DepthWriteMask =   D3D11_DEPTH_WRITE_MASK_ALL;
    depthStencilDesc.DepthFunc      =   D3D11_COMPARISON_LESS;
    depthStencilDesc.StencilEnable  =   true;
    depthStencilDesc.StencilReadMask=   0xFF;
    depthStencilDesc.StencilWriteMask=  0xFF;
    depthStencilDesc.FrontFace.StencilFailOp    =   D3D11_STENCIL_OP_KEEP;
    depthStencilDesc.FrontFace.StencilDepthFailOp=  D3D11_STENCIL_OP_INCR;
    depthStencilDesc.FrontFace.StencilPassOp    =   D3D11_STENCIL_OP_KEEP;
    depthStencilDesc.FrontFace.StencilFunc      =   D3D11_COMPARISON_ALWAYS;
    depthStencilDesc.BackFace.StencilFailOp     =   D3D11_STENCIL_OP_KEEP;
    depthStencilDesc.BackFace.StencilDepthFailOp=   D3D11_STENCIL_OP_DECR;
    depthStencilDesc.BackFace.StencilPassOp     =   D3D11_STENCIL_OP_KEEP;
    depthStencilDesc.BackFace.StencilFunc       =   D3D11_COMPARISON_ALWAYS;
 
    if( FAILED( m_d3d11Device->CreateDepthStencilState( &depthStencilDesc, &m_depthStencilStateEnabled ) ) ){
        gtLogWriter::printError( u"Can't create Direct3D 11 depth stencil state" );
        return false;
    }
 
    m_d3d11DevCon->OMSetDepthStencilState( this->m_depthStencilStateEnabled, 0 );
 
    depthStencilDesc.DepthEnable    =   false;
    if( FAILED( m_d3d11Device->CreateDepthStencilState( &depthStencilDesc, &this->m_depthStencilStateDisabled ) ) ){
        gtLogWriter::printError( u"Can't create Direct3D 11 depth stencil state" );
        return false;
    }
 
    ZeroMemory( &m_depthStencilViewDesc, sizeof( m_depthStencilViewDesc ) );
    m_depthStencilViewDesc.Format       =   DXGI_FORMAT_D32_FLOAT;
    m_depthStencilViewDesc.ViewDimension=   D3D11_DSV_DIMENSION_TEXTURE2D;
    m_depthStencilViewDesc.Texture2D.MipSlice   =   0;
    if( FAILED( m_d3d11Device->CreateDepthStencilView( m_depthStencilBuffer, &m_depthStencilViewDesc, &m_depthStencilView ) ) ){
        gtLogWriter::printError( u"Can't create Direct3D 11 depth stencil view" );
        return false;
    }
 
    m_d3d11DevCon->OMSetRenderTargets( 1, &m_MainTargetView, m_depthStencilView );
 
    D3D11_RASTERIZER_DESC   rasterDesc;
    ZeroMemory( &rasterDesc, sizeof( D3D11_RASTERIZER_DESC ) );
    rasterDesc.AntialiasedLineEnable = true;
    rasterDesc.CullMode = D3D11_CULL_BACK;
    rasterDesc.DepthBias = 0;
    rasterDesc.DepthBiasClamp = 0.0f;
    rasterDesc.DepthClipEnable = true;
    rasterDesc.FillMode = D3D11_FILL_SOLID;
    rasterDesc.FrontCounterClockwise = false;
    rasterDesc.MultisampleEnable = false;
    rasterDesc.ScissorEnable = false;
    rasterDesc.SlopeScaledDepthBias = 0.0f;
 
    if( FAILED( m_d3d11Device->CreateRasterizerState( &rasterDesc, &m_RasterizerSolid ))){
        gtLogWriter::printError( u"Can not create rasterizer state" );
        return false;
    }
 
    rasterDesc.CullMode = D3D11_CULL_NONE;
    m_d3d11Device->CreateRasterizerState( &rasterDesc, &m_RasterizerSolidNoBackFaceCulling );
    rasterDesc.FillMode = D3D11_FILL_WIREFRAME;
    m_d3d11Device->CreateRasterizerState( &rasterDesc, &m_RasterizerWireframeNoBackFaceCulling );
    rasterDesc.CullMode = D3D11_CULL_BACK;
    m_d3d11Device->CreateRasterizerState( &rasterDesc, &m_RasterizerWireframe );
 
    m_d3d11DevCon->RSSetState( m_RasterizerSolid );
 
    D3D11_VIEWPORT viewport;
    viewport.Width      =   (f32)m_params.m_backBufferSize[0u];
    viewport.Height     =   (f32)m_params.m_backBufferSize[1u];
    viewport.MinDepth   =   0.0f;
    viewport.MaxDepth   =   1.0f;
    viewport.TopLeftX   =   0.0f;
    viewport.TopLeftY   =   0.0f;
    m_d3d11DevCon->RSSetViewports( 1, &viewport );
 
    return true;
}
 
void gtDriverD3D11::clearRenderTarget( const gtColor& color ){
    m_d3d11DevCon->ClearRenderTargetView( m_MainTargetView, color.getData() );
}
 
void gtDriverD3D11::beginRender( bool _clearRenderTarget, const gtColor& color ){
    if( !m_beginRender ){
        m_beginRender = true;
 
        if( _clearRenderTarget )
            clearRenderTarget( color );
 
    }
}
 
void gtDriverD3D11::endRender( void ){
    if( m_beginRender ){
        
        if( m_params.m_vSync )
            this->m_SwapChain->Present( 1, 0 );
        else
            this->m_SwapChain->Present( 0, 0 );
 
        m_beginRender = false;
    }
}


У gtWindow добавил новый метод для получения HWND
C++
1
virtual void*   getHandle( void ) = 0;
реализация
C++
1
2
3
void*   gtWindowWin32::getHandle( void ){
    return (void*)m_hWnd;
}

В оконной процедуре gtWindowWin32::WndProc
нужно изменить возвращаемое значение.
C++
1
return DefWindowProc( hWnd, message, wParam, lParam );

В файловую систему добавил функцию получения пути к системной папке.
C++
1
2
    //  возвращает путь к системной папке
    GT_API static gtString getSystemPath( void );
Остальная реализация аналогична как для m_exePath.
Получение пути идёт в конструкторе
gtFileSystemWin32
C++
1
2
3
4
    GetSystemDirectory( szFileName, MAX_PATH );
    m_systemPath.assign( (char16_t*)szFileName );
    m_systemPath += u"/";
    util::stringFlipSlash<gtString>( m_systemPath );
В gtPtr добавлено сравнение
C++
1
2
3
bool    operator==( const gtPtr& v ){
    return m_pointer == v.m_pointer;
}
В gtStackTrace в конструкторе добавил
C++
1
m_log->addRef();
естественно есть ещё всякие мелкие изменения.

===============================

тестовая программа
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
    gtDeviceCreationParameters params;
 
    gtPtr<gtMainSystem> my_system( gtPtrNew<gtMainSystem>( InitializeGoSTEngine(params) ) );
    
    if( !my_system.data() ) return 1;
        
    gtWindowInfo wi;
    
    gtPtr< gtWindow > window1, window2, window3;
 
    wi.m_style = gtWindowInfo::_standart;
    wi.m_style |= gtWindowInfo::_maximize;
    wi.m_style |= gtWindowInfo::_resize;
 
    window1 = gtPtrNew<gtWindow>( my_system->createSystemWindow( wi ) );
    window2 = gtPtrNew<gtWindow>( my_system->createSystemWindow( wi ) );
    window3 = gtPtrNew<gtWindow>( my_system->createSystemWindow( wi ) );
 
        
    gtDriverInfo vparams;
    vparams.m_GUID = GT_GUID_RENDER_D3D11;
    
    vparams.m_outWindow = window1.data();
    gtDriver* driver1 = my_system->createVideoDriver( vparams );
 
    vparams.m_outWindow = window2.data();
    gtDriver* driver2 = my_system->createVideoDriver( vparams );
 
    vparams.m_outWindow = window3.data();
    gtDriver* driver3 = my_system->createVideoDriver( vparams );
 
    while( my_system->update() ){
 
        if( driver1 ){
            driver1->beginRender(true,gtColor(1.f,0.f,0.f,1.f));
            driver1->endRender();
        }
 
        if( driver2 ){
            driver2->beginRender(true,gtColor(0.f,0.f,1.f,1.f));
            driver2->endRender();
        }
 
        if( driver3 ){
            driver3->beginRender(true,gtColor(0.f,1.f,0.f,1.f));
            driver3->endRender();
        }
 
    }

КОДЫ https://github.com/532235/GoST
Миниатюры
Нажмите на изображение для увеличения
Название: yr.JPG
Просмотров: 209
Размер:	33.0 Кб
ID:	4541  
Размещено в Игровой движок
Просмотров 288 Комментарии 0
Всего комментариев 0

Комментарии

 
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru