mirror of
https://github.com/id-Software/DOOM-3-BFG.git
synced 2025-03-14 06:34:10 +00:00
Merged more Vulkan code from vkneo
This commit is contained in:
parent
af02ccb9dc
commit
f180da6f63
15 changed files with 1068 additions and 72 deletions
|
@ -307,12 +307,16 @@ public:
|
|||
levelLoadReferenced = true;
|
||||
}
|
||||
void ActuallyLoadImage( bool fromBackEnd );
|
||||
|
||||
//---------------------------------------------
|
||||
// Platform specific implementations
|
||||
//---------------------------------------------
|
||||
|
||||
#if defined( ID_VULKAN )
|
||||
#if defined( USE_VULKAN )
|
||||
void CreateFromSwapImage( VkImage image, VkImageView imageView, VkFormat format, const VkExtent2D& extent );
|
||||
|
||||
static void EmptyGarbage();
|
||||
|
||||
VkImage GetImage() const
|
||||
{
|
||||
return image;
|
||||
|
@ -345,7 +349,7 @@ public:
|
|||
// they must be a multiple of four for dxt data.
|
||||
void SubImageUpload( int mipLevel, int destX, int destY, int destZ,
|
||||
int width, int height, const void* data,
|
||||
int pixelPitch = 0 ) const;
|
||||
int pixelPitch = 0 );
|
||||
|
||||
// SetPixel is assumed to be a fast memory write on consoles, degenerating to a
|
||||
// SubImageUpload on PCs. Used to update the page mapping images.
|
||||
|
@ -412,6 +416,8 @@ private:
|
|||
static const uint32 TEXTURE_NOT_LOADED = 0xFFFFFFFF;
|
||||
|
||||
#if defined( USE_VULKAN )
|
||||
void CreateSampler();
|
||||
|
||||
bool bIsSwapChainImage;
|
||||
VkFormat internalFormat;
|
||||
VkImage image;
|
||||
|
|
|
@ -248,7 +248,7 @@ On exit, the idImage will have a valid OpenGL texture number that can be bound
|
|||
void idImage::ActuallyLoadImage( bool fromBackEnd )
|
||||
{
|
||||
// if we don't have a rendering context yet, just return
|
||||
if( !R_IsInitialized() )
|
||||
if( !tr.IsInitialized() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -692,7 +692,7 @@ void idImage::GenerateImage( const byte* pic, int width, int height, textureFilt
|
|||
// have filled in the parms. We must have the values set, or
|
||||
// an image match from a shader before the render starts would miss
|
||||
// the generated texture
|
||||
if( !R_IsInitialized() )
|
||||
if( !tr.IsInitialized() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -760,7 +760,7 @@ void idImage::GenerateCubeImage( const byte* pic[6], int size, textureFilter_t f
|
|||
// have filled in the parms. We must have the values set, or
|
||||
// an image match from a shader before the render starts would miss
|
||||
// the generated texture
|
||||
if( !R_IsInitialized() )
|
||||
if( !tr.IsInitialized() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -812,7 +812,7 @@ void idImage::GenerateShadowArray( int width, int height, textureFilter_t filter
|
|||
// have filled in the parms. We must have the values set, or
|
||||
// an image match from a shader before the render starts would miss
|
||||
// the generated texture
|
||||
if( !R_IsInitialized() )
|
||||
if( !tr.IsInitialized() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -290,7 +290,7 @@ void idImage::CopyDepthbuffer( int x, int y, int imageWidth, int imageHeight )
|
|||
idImage::SubImageUpload
|
||||
========================
|
||||
*/
|
||||
void idImage::SubImageUpload( int mipLevel, int x, int y, int z, int width, int height, const void* pic, int pixelPitch ) const
|
||||
void idImage::SubImageUpload( int mipLevel, int x, int y, int z, int width, int height, const void* pic, int pixelPitch )
|
||||
{
|
||||
assert( x >= 0 && y >= 0 && mipLevel >= 0 && width >= 0 && height >= 0 && mipLevel < opts.numLevels );
|
||||
|
||||
|
@ -763,7 +763,7 @@ void idImage::AllocImage()
|
|||
// have filled in the parms. We must have the values set, or
|
||||
// an image match from a shader before OpenGL starts would miss
|
||||
// the generated texture
|
||||
if( !R_IsInitialized() )
|
||||
if( !tr.IsInitialized() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -118,17 +118,7 @@ bool GL_CheckErrors_( const char* filename, int line )
|
|||
}
|
||||
|
||||
|
||||
static bool r_initialized = false;
|
||||
|
||||
/*
|
||||
=============================
|
||||
R_IsInitialized
|
||||
=============================
|
||||
*/
|
||||
bool R_IsInitialized()
|
||||
{
|
||||
return r_initialized;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -470,7 +460,7 @@ void idRenderBackend::Init()
|
|||
{
|
||||
common->Printf( "----- R_InitOpenGL -----\n" );
|
||||
|
||||
if( R_IsInitialized() )
|
||||
if( tr.IsInitialized() )
|
||||
{
|
||||
common->FatalError( "R_InitOpenGL called while active" );
|
||||
}
|
||||
|
@ -532,14 +522,12 @@ void idRenderBackend::Init()
|
|||
glConfig.maxTextureSize = 256;
|
||||
}
|
||||
|
||||
r_initialized = true;
|
||||
|
||||
// recheck all the extensions (FIXME: this might be dangerous)
|
||||
R_CheckPortableExtensions();
|
||||
|
||||
renderProgManager.Init();
|
||||
|
||||
r_initialized = true;
|
||||
tr.SetInitialized();
|
||||
|
||||
// allocate the vertex array range or vertex objects
|
||||
vertexCache.Init( glConfig.uniformBufferOffsetAlignment );
|
||||
|
@ -554,7 +542,6 @@ void idRenderBackend::Init()
|
|||
void idRenderBackend::Shutdown()
|
||||
{
|
||||
GLimp_Shutdown();
|
||||
r_initialized = false;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -154,9 +154,14 @@ struct vulkanContext_t
|
|||
uint64 stencilOperations[ STENCIL_FACE_NUM ];
|
||||
|
||||
VkInstance instance;
|
||||
|
||||
// selected physical device
|
||||
VkPhysicalDevice physicalDevice;
|
||||
VkPhysicalDeviceFeatures physicalDeviceFeatures;
|
||||
|
||||
// logical device
|
||||
VkDevice device;
|
||||
|
||||
VkQueue graphicsQueue;
|
||||
VkQueue presentQueue;
|
||||
int graphicsFamilyIdx;
|
||||
|
@ -167,7 +172,10 @@ struct vulkanContext_t
|
|||
idList< const char* > deviceExtensions;
|
||||
idList< const char* > validationLayers;
|
||||
|
||||
// selected GPU
|
||||
gpuInfo_t* gpu;
|
||||
|
||||
// all GPUs found on the system
|
||||
idList< gpuInfo_t > gpus;
|
||||
|
||||
VkCommandPool commandPool;
|
||||
|
|
|
@ -704,6 +704,10 @@ public:
|
|||
// external functions
|
||||
virtual void Init();
|
||||
virtual void Shutdown();
|
||||
virtual bool IsInitialized() const
|
||||
{
|
||||
return bInitialized;
|
||||
}
|
||||
virtual void ResetGuiModels();
|
||||
virtual void InitOpenGL();
|
||||
virtual void ShutdownOpenGL();
|
||||
|
@ -765,6 +769,10 @@ public:
|
|||
|
||||
void PrintPerformanceCounters();
|
||||
|
||||
void SetInitialized()
|
||||
{
|
||||
bInitialized = true;
|
||||
}
|
||||
|
||||
public:
|
||||
// internal functions
|
||||
|
@ -850,6 +858,9 @@ public:
|
|||
idRenderBackend backend;
|
||||
|
||||
unsigned timerQueryId; // for GL_TIME_ELAPSED_EXT queries
|
||||
|
||||
private:
|
||||
bool bInitialized;
|
||||
};
|
||||
|
||||
extern idRenderSystemLocal tr;
|
||||
|
|
|
@ -1968,10 +1968,12 @@ idRenderProgManager::SetUniformValue
|
|||
*/
|
||||
void idRenderProgManager::SetUniformValue( const renderParm_t rp, const float* value )
|
||||
{
|
||||
#if !defined(USE_VULKAN)
|
||||
for( int i = 0; i < 4; i++ )
|
||||
{
|
||||
glslUniforms[rp][i] = value[i];
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -238,7 +238,8 @@ idRenderSystemLocal::idRenderSystemLocal
|
|||
idRenderSystemLocal::idRenderSystemLocal() :
|
||||
unitSquareTriangles( NULL ),
|
||||
zeroOneCubeTriangles( NULL ),
|
||||
testImageTriangles( NULL )
|
||||
testImageTriangles( NULL ),
|
||||
bInitialized( false )
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
@ -311,7 +312,7 @@ idRenderSystemLocal::DrawStretchPic
|
|||
static triIndex_t quadPicIndexes[6] = { 3, 0, 2, 2, 0, 1 };
|
||||
void idRenderSystemLocal::DrawStretchPic( const idVec4& topLeft, const idVec4& topRight, const idVec4& bottomRight, const idVec4& bottomLeft, const idMaterial* material )
|
||||
{
|
||||
if( !R_IsInitialized() )
|
||||
if( !IsInitialized() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -366,7 +367,7 @@ idRenderSystemLocal::DrawStretchTri
|
|||
*/
|
||||
void idRenderSystemLocal::DrawStretchTri( const idVec2& p1, const idVec2& p2, const idVec2& p3, const idVec2& t1, const idVec2& t2, const idVec2& t3, const idMaterial* material )
|
||||
{
|
||||
if( !R_IsInitialized() )
|
||||
if( !IsInitialized() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -635,14 +636,14 @@ void idRenderSystemLocal::SwapCommandBuffers_FinishRendering(
|
|||
*gpuMicroSec = 0; // until shown otherwise
|
||||
}
|
||||
|
||||
if( !R_IsInitialized() )
|
||||
if( !IsInitialized() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// After coming back from an autoswap, we won't have anything to render
|
||||
if( frameData->cmdHead->next != NULL )
|
||||
if( frameData && frameData->cmdHead->next != NULL )
|
||||
{
|
||||
// wait for our fence to hit, which means the swap has actually happened
|
||||
// We must do this before clearing any resources the GPU may be using
|
||||
|
@ -705,7 +706,7 @@ idRenderSystemLocal::SwapCommandBuffers_FinishCommandBuffers
|
|||
*/
|
||||
const emptyCommand_t* idRenderSystemLocal::SwapCommandBuffers_FinishCommandBuffers()
|
||||
{
|
||||
if( !R_IsInitialized() )
|
||||
if( !IsInitialized() )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
@ -854,7 +855,7 @@ idRenderSystemLocal::CropRenderSize
|
|||
*/
|
||||
void idRenderSystemLocal::CropRenderSize( int width, int height )
|
||||
{
|
||||
if( !R_IsInitialized() )
|
||||
if( !IsInitialized() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -901,7 +902,7 @@ idRenderSystemLocal::UnCrop
|
|||
*/
|
||||
void idRenderSystemLocal::UnCrop()
|
||||
{
|
||||
if( !R_IsInitialized() )
|
||||
if( !IsInitialized() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -936,7 +937,7 @@ idRenderSystemLocal::CaptureRenderToImage
|
|||
*/
|
||||
void idRenderSystemLocal::CaptureRenderToImage( const char* imageName, bool clearColorAfterCopy )
|
||||
{
|
||||
if( !R_IsInitialized() )
|
||||
if( !IsInitialized() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -981,7 +982,7 @@ idRenderSystemLocal::CaptureRenderToFile
|
|||
*/
|
||||
void idRenderSystemLocal::CaptureRenderToFile( const char* fileName, bool fixAlpha )
|
||||
{
|
||||
if( !R_IsInitialized() )
|
||||
if( !IsInitialized() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -199,8 +199,6 @@ struct glconfig_t
|
|||
|
||||
struct emptyCommand_t;
|
||||
|
||||
bool R_IsInitialized();
|
||||
|
||||
const int SMALLCHAR_WIDTH = 8;
|
||||
const int SMALLCHAR_HEIGHT = 16;
|
||||
const int BIGCHAR_WIDTH = 16;
|
||||
|
@ -229,6 +227,8 @@ public:
|
|||
// only called before quitting
|
||||
virtual void Shutdown() = 0;
|
||||
|
||||
virtual bool IsInitialized() const = 0;
|
||||
|
||||
virtual void ResetGuiModels() = 0;
|
||||
|
||||
virtual void InitOpenGL() = 0;
|
||||
|
|
|
@ -1816,7 +1816,7 @@ R_VidRestart_f
|
|||
void R_VidRestart_f( const idCmdArgs& args )
|
||||
{
|
||||
// if OpenGL isn't started, do nothing
|
||||
if( !R_IsInitialized() )
|
||||
if( !tr.IsInitialized() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -2209,6 +2209,9 @@ void idRenderSystemLocal::Init()
|
|||
|
||||
R_InitCommands();
|
||||
|
||||
// allocate the frame data, which may be more if smp is enabled
|
||||
R_InitFrameData();
|
||||
|
||||
guiModel = new( TAG_RENDER ) idGuiModel;
|
||||
guiModel->Clear();
|
||||
tr_guiModel = guiModel; // for DeviceContext fast path
|
||||
|
@ -2253,6 +2256,8 @@ void idRenderSystemLocal::Init()
|
|||
|
||||
frontEndJobList = parallelJobManager->AllocJobList( JOBLIST_RENDERER_FRONTEND, JOBLIST_PRIORITY_MEDIUM, 2048, 0, NULL );
|
||||
|
||||
bInitialized = true;
|
||||
|
||||
// make sure the command buffers are ready to accept the first screen update
|
||||
SwapCommandBuffers( NULL, NULL, NULL, NULL );
|
||||
|
||||
|
@ -2271,7 +2276,7 @@ void idRenderSystemLocal::Shutdown()
|
|||
|
||||
fonts.DeleteContents();
|
||||
|
||||
if( R_IsInitialized() )
|
||||
if( IsInitialized() )
|
||||
{
|
||||
globalImages->PurgeAllImages();
|
||||
}
|
||||
|
@ -2303,6 +2308,8 @@ void idRenderSystemLocal::Shutdown()
|
|||
Clear();
|
||||
|
||||
ShutdownOpenGL();
|
||||
|
||||
bInitialized = false;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2434,7 +2441,7 @@ idRenderSystemLocal::InitOpenGL
|
|||
void idRenderSystemLocal::InitOpenGL()
|
||||
{
|
||||
// if OpenGL isn't started, start it now
|
||||
if( !R_IsInitialized() )
|
||||
if( !IsInitialized() )
|
||||
{
|
||||
backend.Init();
|
||||
|
||||
|
@ -2471,7 +2478,7 @@ idRenderSystemLocal::IsOpenGLRunning
|
|||
*/
|
||||
bool idRenderSystemLocal::IsOpenGLRunning() const
|
||||
{
|
||||
return R_IsInitialized();
|
||||
return IsInitialized();
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -895,7 +895,7 @@ to handle mirrors,
|
|||
*/
|
||||
void idRenderWorldLocal::RenderScene( const renderView_t* renderView )
|
||||
{
|
||||
if( !R_IsInitialized() )
|
||||
if( !tr.IsInitialized() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -1749,7 +1749,7 @@ If this isn't called, they will all be dynamically generated
|
|||
*/
|
||||
void idRenderWorldLocal::GenerateAllInteractions()
|
||||
{
|
||||
if( !R_IsInitialized() )
|
||||
if( !tr.IsInitialized() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -3,7 +3,8 @@
|
|||
|
||||
Doom 3 BFG Edition GPL Source Code
|
||||
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
|
||||
Copyright (C) 2013-2016 Robert Beckebans
|
||||
Copyright (C) 2013-2018 Robert Beckebans
|
||||
Copyright (C) 2016-2017 Dustin Land
|
||||
|
||||
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
|
||||
|
||||
|
@ -31,11 +32,122 @@ If you have questions concerning this license or the applicable additional terms
|
|||
|
||||
/*
|
||||
================================================================================================
|
||||
Contains the Image implementation for OpenGL.
|
||||
Contains the Image implementation for Vulkan
|
||||
================================================================================================
|
||||
*/
|
||||
|
||||
#include "../RenderCommon.h"
|
||||
#include "Staging_VK.h"
|
||||
|
||||
int idImage::garbageIndex = 0;
|
||||
#if defined( ID_USE_AMD_ALLOCATOR )
|
||||
idList< VmaAllocation > idImage::m_allocationGarbage[ NUM_FRAME_DATA ];
|
||||
#else
|
||||
idList< vulkanAllocation_t > idImage::allocationGarbage[ NUM_FRAME_DATA ];
|
||||
#endif
|
||||
idList< VkImage > idImage::imageGarbage[ NUM_FRAME_DATA ];
|
||||
idList< VkImageView > idImage::viewGarbage[ NUM_FRAME_DATA ];
|
||||
idList< VkSampler > idImage::samplerGarbage[ NUM_FRAME_DATA ];
|
||||
|
||||
|
||||
/*
|
||||
====================
|
||||
VK_GetFormatFromTextureFormat
|
||||
====================
|
||||
*/
|
||||
static VkFormat VK_GetFormatFromTextureFormat( const textureFormat_t format )
|
||||
{
|
||||
switch( format )
|
||||
{
|
||||
case FMT_RGBA8:
|
||||
return VK_FORMAT_R8G8B8A8_UNORM;
|
||||
case FMT_XRGB8:
|
||||
return VK_FORMAT_R8G8B8_UNORM;
|
||||
case FMT_ALPHA:
|
||||
return VK_FORMAT_R8_UNORM;
|
||||
case FMT_L8A8:
|
||||
return VK_FORMAT_R8G8_UNORM;
|
||||
case FMT_LUM8:
|
||||
return VK_FORMAT_R8_UNORM;
|
||||
case FMT_INT8:
|
||||
return VK_FORMAT_R8_UNORM;
|
||||
case FMT_DXT1:
|
||||
return VK_FORMAT_BC1_RGB_UNORM_BLOCK;
|
||||
case FMT_DXT5:
|
||||
return VK_FORMAT_BC3_UNORM_BLOCK;
|
||||
case FMT_DEPTH:
|
||||
return vkcontext.depthFormat;
|
||||
case FMT_X16:
|
||||
return VK_FORMAT_R16_UNORM;
|
||||
case FMT_Y16_X16:
|
||||
return VK_FORMAT_R16G16_UNORM;
|
||||
case FMT_RGB565:
|
||||
return VK_FORMAT_R5G6B5_UNORM_PACK16;
|
||||
default:
|
||||
return VK_FORMAT_UNDEFINED;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
VK_GetComponentMappingFromTextureFormat
|
||||
====================
|
||||
*/
|
||||
static VkComponentMapping VK_GetComponentMappingFromTextureFormat( const textureFormat_t format, textureColor_t color )
|
||||
{
|
||||
VkComponentMapping componentMapping =
|
||||
{
|
||||
VK_COMPONENT_SWIZZLE_ZERO,
|
||||
VK_COMPONENT_SWIZZLE_ZERO,
|
||||
VK_COMPONENT_SWIZZLE_ZERO,
|
||||
VK_COMPONENT_SWIZZLE_ZERO
|
||||
};
|
||||
|
||||
if( color == CFM_GREEN_ALPHA )
|
||||
{
|
||||
componentMapping.r = VK_COMPONENT_SWIZZLE_ONE;
|
||||
componentMapping.g = VK_COMPONENT_SWIZZLE_ONE;
|
||||
componentMapping.b = VK_COMPONENT_SWIZZLE_ONE;
|
||||
componentMapping.a = VK_COMPONENT_SWIZZLE_G;
|
||||
return componentMapping;
|
||||
}
|
||||
|
||||
switch( format )
|
||||
{
|
||||
case FMT_LUM8:
|
||||
componentMapping.r = VK_COMPONENT_SWIZZLE_R;
|
||||
componentMapping.g = VK_COMPONENT_SWIZZLE_R;
|
||||
componentMapping.b = VK_COMPONENT_SWIZZLE_R;
|
||||
componentMapping.a = VK_COMPONENT_SWIZZLE_ONE;
|
||||
break;
|
||||
case FMT_L8A8:
|
||||
componentMapping.r = VK_COMPONENT_SWIZZLE_R;
|
||||
componentMapping.g = VK_COMPONENT_SWIZZLE_R;
|
||||
componentMapping.b = VK_COMPONENT_SWIZZLE_R;
|
||||
componentMapping.a = VK_COMPONENT_SWIZZLE_G;
|
||||
break;
|
||||
case FMT_ALPHA:
|
||||
componentMapping.r = VK_COMPONENT_SWIZZLE_ONE;
|
||||
componentMapping.g = VK_COMPONENT_SWIZZLE_ONE;
|
||||
componentMapping.b = VK_COMPONENT_SWIZZLE_ONE;
|
||||
componentMapping.a = VK_COMPONENT_SWIZZLE_R;
|
||||
break;
|
||||
case FMT_INT8:
|
||||
componentMapping.r = VK_COMPONENT_SWIZZLE_R;
|
||||
componentMapping.g = VK_COMPONENT_SWIZZLE_R;
|
||||
componentMapping.b = VK_COMPONENT_SWIZZLE_R;
|
||||
componentMapping.a = VK_COMPONENT_SWIZZLE_R;
|
||||
break;
|
||||
default:
|
||||
componentMapping.r = VK_COMPONENT_SWIZZLE_R;
|
||||
componentMapping.g = VK_COMPONENT_SWIZZLE_G;
|
||||
componentMapping.b = VK_COMPONENT_SWIZZLE_B;
|
||||
componentMapping.a = VK_COMPONENT_SWIZZLE_A;
|
||||
break;
|
||||
}
|
||||
|
||||
return componentMapping;
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
|
@ -44,10 +156,14 @@ idImage::idImage
|
|||
*/
|
||||
idImage::idImage( const char* name ) : imgName( name )
|
||||
{
|
||||
//texnum = TEXTURE_NOT_LOADED;
|
||||
//internalFormat = 0;
|
||||
//dataFormat = 0;
|
||||
//dataType = 0;
|
||||
// Vulkan specific
|
||||
bIsSwapChainImage = false;
|
||||
internalFormat = VK_FORMAT_UNDEFINED;
|
||||
image = VK_NULL_HANDLE;
|
||||
view = VK_NULL_HANDLE;
|
||||
layout = VK_IMAGE_LAYOUT_GENERAL;
|
||||
sampler = VK_NULL_HANDLE;
|
||||
|
||||
generatorFunction = NULL;
|
||||
filter = TF_DEFAULT;
|
||||
repeat = TR_REPEAT;
|
||||
|
@ -69,7 +185,10 @@ idImage::~idImage
|
|||
*/
|
||||
idImage::~idImage()
|
||||
{
|
||||
PurgeImage();
|
||||
if( !bIsSwapChainImage )
|
||||
{
|
||||
PurgeImage();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -82,6 +201,156 @@ bool idImage::IsLoaded() const
|
|||
return image != VK_NULL_HANDLE; // TODO_VK maybe do something better than this.
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
idImage::CreateFromSwapImage
|
||||
====================
|
||||
*/
|
||||
void idImage::CreateFromSwapImage( VkImage image, VkImageView imageView, VkFormat format, const VkExtent2D& extent )
|
||||
{
|
||||
image = image;
|
||||
view = imageView;
|
||||
internalFormat = format;
|
||||
opts.textureType = TT_2D;
|
||||
opts.format = FMT_RGBA8;
|
||||
opts.numLevels = 1;
|
||||
opts.width = extent.width;
|
||||
opts.height = extent.height;
|
||||
bIsSwapChainImage = true;
|
||||
|
||||
// TODO_VK may need to setup more state here.
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
idImage::CreateSampler
|
||||
====================
|
||||
*/
|
||||
void idImage::CreateSampler()
|
||||
{
|
||||
VkSamplerCreateInfo createInfo = {};
|
||||
createInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
|
||||
createInfo.maxAnisotropy = 1.0f;
|
||||
createInfo.anisotropyEnable = VK_FALSE;
|
||||
createInfo.compareEnable = ( opts.format == FMT_DEPTH );
|
||||
createInfo.compareOp = ( opts.format == FMT_DEPTH ) ? VK_COMPARE_OP_LESS_OR_EQUAL : VK_COMPARE_OP_NEVER;
|
||||
|
||||
switch( filter )
|
||||
{
|
||||
case TF_DEFAULT:
|
||||
case TF_LINEAR:
|
||||
createInfo.minFilter = VK_FILTER_LINEAR;
|
||||
createInfo.magFilter = VK_FILTER_LINEAR;
|
||||
createInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
|
||||
break;
|
||||
|
||||
case TF_NEAREST:
|
||||
createInfo.minFilter = VK_FILTER_NEAREST;
|
||||
createInfo.magFilter = VK_FILTER_NEAREST;
|
||||
createInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST;
|
||||
break;
|
||||
|
||||
// RB:
|
||||
case TF_NEAREST_MIPMAP:
|
||||
createInfo.minFilter = VK_FILTER_NEAREST;
|
||||
createInfo.magFilter = VK_FILTER_NEAREST;
|
||||
createInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
|
||||
break;
|
||||
|
||||
default:
|
||||
idLib::FatalError( "idImage::CreateSampler: unrecognized texture filter %d", filter );
|
||||
}
|
||||
|
||||
switch( repeat )
|
||||
{
|
||||
case TR_REPEAT:
|
||||
createInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT;
|
||||
createInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT;
|
||||
createInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT;
|
||||
break;
|
||||
|
||||
case TR_CLAMP:
|
||||
createInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
|
||||
createInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
|
||||
createInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
|
||||
break;
|
||||
|
||||
case TR_CLAMP_TO_ZERO_ALPHA:
|
||||
createInfo.borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK;
|
||||
createInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER;
|
||||
createInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER;
|
||||
createInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER;
|
||||
break;
|
||||
|
||||
case TR_CLAMP_TO_ZERO:
|
||||
createInfo.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK;
|
||||
createInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER;
|
||||
createInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER;
|
||||
createInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER;
|
||||
break;
|
||||
default:
|
||||
idLib::FatalError( "idImage::CreateSampler: unrecognized texture repeat mode %d", repeat );
|
||||
}
|
||||
|
||||
ID_VK_CHECK( vkCreateSampler( vkcontext.device, &createInfo, NULL, &sampler ) );
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
idImage::EmptyGarbage
|
||||
====================
|
||||
*/
|
||||
void idImage::EmptyGarbage()
|
||||
{
|
||||
garbageIndex = ( garbageIndex + 1 ) % NUM_FRAME_DATA;
|
||||
|
||||
#if defined( ID_USE_AMD_ALLOCATOR )
|
||||
idList< VmaAllocation >& allocationsToFree = allocationGarbage[ garbageIndex ];
|
||||
#else
|
||||
idList< vulkanAllocation_t >& allocationsToFree = allocationGarbage[ garbageIndex ];
|
||||
#endif
|
||||
idList< VkImage >& imagesToFree = imageGarbage[ garbageIndex ];
|
||||
idList< VkImageView >& viewsToFree = viewGarbage[ garbageIndex ];
|
||||
idList< VkSampler >& samplersToFree = samplerGarbage[ garbageIndex ];
|
||||
|
||||
#if defined( ID_USE_AMD_ALLOCATOR )
|
||||
const int numAllocations = allocationsToFree.Num();
|
||||
for( int i = 0; i < numAllocations; ++i )
|
||||
{
|
||||
vmaDestroyImage( vmaAllocator, imagesToFree[ i ], allocationsToFree[ i ] );
|
||||
}
|
||||
#else
|
||||
const int numAllocations = allocationsToFree.Num();
|
||||
for( int i = 0; i < numAllocations; ++i )
|
||||
{
|
||||
vulkanAllocator.Free( allocationsToFree[ i ] );
|
||||
}
|
||||
|
||||
const int numImages = imagesToFree.Num();
|
||||
for( int i = 0; i < numImages; ++i )
|
||||
{
|
||||
vkDestroyImage( vkcontext.device, imagesToFree[ i ], NULL );
|
||||
}
|
||||
#endif
|
||||
|
||||
const int numViews = viewsToFree.Num();
|
||||
for( int i = 0; i < numViews; ++i )
|
||||
{
|
||||
vkDestroyImageView( vkcontext.device, viewsToFree[ i ], NULL );
|
||||
}
|
||||
|
||||
const int numSamplers = samplersToFree.Num();
|
||||
for( int i = 0; i < numSamplers; ++i )
|
||||
{
|
||||
vkDestroySampler( vkcontext.device, samplersToFree[ i ], NULL );
|
||||
}
|
||||
|
||||
allocationsToFree.Clear();
|
||||
imagesToFree.Clear();
|
||||
viewsToFree.Clear();
|
||||
samplersToFree.Clear();
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
Bind
|
||||
|
@ -119,9 +388,77 @@ void idImage::CopyDepthbuffer( int x, int y, int imageWidth, int imageHeight )
|
|||
idImage::SubImageUpload
|
||||
========================
|
||||
*/
|
||||
void idImage::SubImageUpload( int mipLevel, int x, int y, int z, int width, int height, const void* pic, int pixelPitch ) const
|
||||
void idImage::SubImageUpload( int mipLevel, int x, int y, int z, int width, int height, const void* pic, int pixelPitch )
|
||||
{
|
||||
|
||||
assert( x >= 0 && y >= 0 && mipLevel >= 0 && width >= 0 && height >= 0 && mipLevel < opts.numLevels );
|
||||
|
||||
if( IsCompressed() )
|
||||
{
|
||||
width = ( width + 3 ) & ~3;
|
||||
height = ( height + 3 ) & ~3;
|
||||
}
|
||||
|
||||
int size = width * height * BitsForFormat( opts.format ) / 8;
|
||||
|
||||
VkBuffer buffer;
|
||||
VkCommandBuffer commandBuffer;
|
||||
int offset = 0;
|
||||
byte* data = stagingManager.Stage( size, 16, commandBuffer, buffer, offset );
|
||||
if( opts.format == FMT_RGB565 )
|
||||
{
|
||||
byte* imgData = ( byte* )pic;
|
||||
for( int i = 0; i < size; i += 2 )
|
||||
{
|
||||
data[ i ] = imgData[ i + 1 ];
|
||||
data[ i + 1 ] = imgData[ i ];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy( data, pic, size );
|
||||
}
|
||||
|
||||
VkBufferImageCopy imgCopy = {};
|
||||
imgCopy.bufferOffset = offset;
|
||||
imgCopy.bufferRowLength = pixelPitch;
|
||||
imgCopy.bufferImageHeight = height;
|
||||
imgCopy.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
imgCopy.imageSubresource.layerCount = 1;
|
||||
imgCopy.imageSubresource.mipLevel = mipLevel;
|
||||
imgCopy.imageSubresource.baseArrayLayer = z;
|
||||
imgCopy.imageOffset.x = x;
|
||||
imgCopy.imageOffset.y = y;
|
||||
imgCopy.imageOffset.z = 0;
|
||||
imgCopy.imageExtent.width = width;
|
||||
imgCopy.imageExtent.height = height;
|
||||
imgCopy.imageExtent.depth = 1;
|
||||
|
||||
VkImageMemoryBarrier barrier = {};
|
||||
barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
|
||||
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
barrier.image = image;
|
||||
barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
barrier.subresourceRange.baseMipLevel = 0;
|
||||
barrier.subresourceRange.levelCount = opts.numLevels;
|
||||
barrier.subresourceRange.baseArrayLayer = z;
|
||||
barrier.subresourceRange.layerCount = 1;
|
||||
|
||||
barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
|
||||
barrier.srcAccessMask = 0;
|
||||
barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||
vkCmdPipelineBarrier( commandBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, NULL, 0, NULL, 1, &barrier );
|
||||
|
||||
vkCmdCopyBufferToImage( commandBuffer, buffer, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &imgCopy );
|
||||
|
||||
barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
|
||||
barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||
barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||
barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
|
||||
vkCmdPipelineBarrier( commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, 0, 0, NULL, 0, NULL, 1, &barrier );
|
||||
|
||||
layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -166,7 +503,74 @@ This should not be done during normal game-play, if you can avoid it.
|
|||
*/
|
||||
void idImage::AllocImage()
|
||||
{
|
||||
|
||||
PurgeImage();
|
||||
|
||||
internalFormat = VK_GetFormatFromTextureFormat( opts.format );
|
||||
|
||||
// Create Sampler
|
||||
CreateSampler();
|
||||
|
||||
VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_SAMPLED_BIT;
|
||||
if( opts.format == FMT_DEPTH )
|
||||
{
|
||||
usageFlags |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
|
||||
}
|
||||
else
|
||||
{
|
||||
usageFlags |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
|
||||
}
|
||||
|
||||
// Create Image
|
||||
VkImageCreateInfo imageCreateInfo = {};
|
||||
imageCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
|
||||
imageCreateInfo.flags = ( opts.textureType == TT_CUBIC ) ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : 0;
|
||||
imageCreateInfo.imageType = VK_IMAGE_TYPE_2D;
|
||||
imageCreateInfo.format = internalFormat;
|
||||
imageCreateInfo.extent.width = opts.width;
|
||||
imageCreateInfo.extent.height = opts.height;
|
||||
imageCreateInfo.extent.depth = 1;
|
||||
imageCreateInfo.mipLevels = opts.numLevels;
|
||||
imageCreateInfo.arrayLayers = ( opts.textureType == TT_CUBIC ) ? 6 : 1;
|
||||
imageCreateInfo.samples = static_cast< VkSampleCountFlagBits >( opts.samples );
|
||||
imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
|
||||
imageCreateInfo.usage = usageFlags;
|
||||
imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
imageCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||
|
||||
#if defined( ID_USE_AMD_ALLOCATOR )
|
||||
VmaMemoryRequirements vmaReq = {};
|
||||
vmaReq.usage = VMA_MEMORY_USAGE_GPU_ONLY;
|
||||
|
||||
ID_VK_CHECK( vmaCreateImage( vmaAllocator, &imageCreateInfo, &vmaReq, &image, &allocation, NULL ) );
|
||||
#else
|
||||
ID_VK_CHECK( vkCreateImage( vkcontext.device, &imageCreateInfo, NULL, &image ) );
|
||||
|
||||
VkMemoryRequirements memoryRequirements;
|
||||
vkGetImageMemoryRequirements( vkcontext.device, image, &memoryRequirements );
|
||||
|
||||
allocation = vulkanAllocator.Allocate(
|
||||
memoryRequirements.size,
|
||||
memoryRequirements.alignment,
|
||||
memoryRequirements.memoryTypeBits,
|
||||
VULKAN_MEMORY_USAGE_GPU_ONLY,
|
||||
VULKAN_ALLOCATION_TYPE_IMAGE_OPTIMAL );
|
||||
|
||||
ID_VK_CHECK( vkBindImageMemory( vkcontext.device, image, allocation.deviceMemory, allocation.offset ) );
|
||||
#endif
|
||||
|
||||
// Create Image View
|
||||
VkImageViewCreateInfo viewCreateInfo = {};
|
||||
viewCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
||||
viewCreateInfo.image = image;
|
||||
viewCreateInfo.viewType = ( opts.textureType == TT_CUBIC ) ? VK_IMAGE_VIEW_TYPE_CUBE : VK_IMAGE_VIEW_TYPE_2D;
|
||||
viewCreateInfo.format = internalFormat;
|
||||
viewCreateInfo.components = VK_GetComponentMappingFromTextureFormat( opts.format, opts.colorFormat );
|
||||
viewCreateInfo.subresourceRange.aspectMask = ( opts.format == FMT_DEPTH ) ? VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT : VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
viewCreateInfo.subresourceRange.levelCount = opts.numLevels;
|
||||
viewCreateInfo.subresourceRange.layerCount = ( opts.textureType == TT_CUBIC ) ? 6 : 1;
|
||||
viewCreateInfo.subresourceRange.baseMipLevel = 0;
|
||||
|
||||
ID_VK_CHECK( vkCreateImageView( vkcontext.device, &viewCreateInfo, NULL, &view ) );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -176,7 +580,27 @@ idImage::PurgeImage
|
|||
*/
|
||||
void idImage::PurgeImage()
|
||||
{
|
||||
|
||||
if( sampler != VK_NULL_HANDLE )
|
||||
{
|
||||
samplerGarbage[ garbageIndex ].Append( sampler );
|
||||
sampler = VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
if( image != VK_NULL_HANDLE )
|
||||
{
|
||||
allocationGarbage[ garbageIndex ].Append( allocation );
|
||||
viewGarbage[ garbageIndex ].Append( view );
|
||||
imageGarbage[ garbageIndex ].Append( image );
|
||||
|
||||
#if defined( ID_USE_AMD_ALLOCATOR )
|
||||
allocation = NULL;
|
||||
#else
|
||||
allocation = vulkanAllocation_t();
|
||||
#endif
|
||||
|
||||
view = VK_NULL_HANDLE;
|
||||
image = VK_NULL_HANDLE;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -33,6 +33,7 @@ If you have questions concerning this license or the applicable additional terms
|
|||
|
||||
#include "../RenderCommon.h"
|
||||
#include "../RenderBackend.h"
|
||||
#include "Staging_VK.h"
|
||||
#include "../../framework/Common_local.h"
|
||||
|
||||
idCVar r_drawFlickerBox( "r_drawFlickerBox", "0", CVAR_RENDERER | CVAR_BOOL, "visual test for dropping frames" );
|
||||
|
@ -152,23 +153,23 @@ VKAPI_ATTR VkBool32 VKAPI_CALL DebugCallback( VkDebugReportFlagsEXT msgFlags, Vk
|
|||
{
|
||||
if( msgFlags & VK_DEBUG_REPORT_ERROR_BIT_EXT )
|
||||
{
|
||||
idLib::Printf( "Vulkan ERROR: [ %s ] Code %d : '%s'\n", layerPrefix, msgCode, msg );
|
||||
idLib::Printf( "[Vulkan] ERROR: [ %s ] Code %d : '%s'\n", layerPrefix, msgCode, msg );
|
||||
}
|
||||
else if( msgFlags & VK_DEBUG_REPORT_WARNING_BIT_EXT )
|
||||
{
|
||||
idLib::Printf( "Vulkan WARNING: [ %s ] Code %d : '%s'\n", layerPrefix, msgCode, msg );
|
||||
idLib::Printf( "[Vulkan] WARNING: [ %s ] Code %d : '%s'\n", layerPrefix, msgCode, msg );
|
||||
}
|
||||
else if( msgFlags & VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT )
|
||||
{
|
||||
idLib::Printf( "Vulkan PERFORMANCE WARNING: [ %s ] Code %d : '%s'\n", layerPrefix, msgCode, msg );
|
||||
idLib::Printf( "[Vulkan] PERFORMANCE WARNING: [ %s ] Code %d : '%s'\n", layerPrefix, msgCode, msg );
|
||||
}
|
||||
else if( msgFlags & VK_DEBUG_REPORT_INFORMATION_BIT_EXT )
|
||||
{
|
||||
idLib::Printf( "Vulkan INFO: [ %s ] Code %d : '%s'\n", layerPrefix, msgCode, msg );
|
||||
idLib::Printf( "[Vulkan] INFO: [ %s ] Code %d : '%s'\n", layerPrefix, msgCode, msg );
|
||||
}
|
||||
else if( msgFlags & VK_DEBUG_REPORT_DEBUG_BIT_EXT )
|
||||
{
|
||||
idLib::Printf( "Vulkan DEBUG: [ %s ] Code %d : '%s'\n", layerPrefix, msgCode, msg );
|
||||
idLib::Printf( "[Vulkan] DEBUG: [ %s ] Code %d : '%s'\n", layerPrefix, msgCode, msg );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -375,6 +376,7 @@ static void EnumeratePhysicalDevices()
|
|||
gpuInfo_t& gpu = vkcontext.gpus[ i ];
|
||||
gpu.device = devices[ i ];
|
||||
|
||||
// get Queue family properties
|
||||
{
|
||||
uint32 numQueues = 0;
|
||||
vkGetPhysicalDeviceQueueFamilyProperties( gpu.device, &numQueues, NULL );
|
||||
|
@ -385,6 +387,7 @@ static void EnumeratePhysicalDevices()
|
|||
ID_VK_VALIDATE( numQueues > 0, "vkGetPhysicalDeviceQueueFamilyProperties returned zero queues." );
|
||||
}
|
||||
|
||||
// grab available Vulkan extensions
|
||||
{
|
||||
uint32 numExtension;
|
||||
ID_VK_CHECK( vkEnumerateDeviceExtensionProperties( gpu.device, NULL, &numExtension, NULL ) );
|
||||
|
@ -402,6 +405,7 @@ static void EnumeratePhysicalDevices()
|
|||
#endif
|
||||
}
|
||||
|
||||
// grab surface specific information
|
||||
ID_VK_CHECK( vkGetPhysicalDeviceSurfaceCapabilitiesKHR( gpu.device, vkcontext.surface, &gpu.surfaceCaps ) );
|
||||
|
||||
{
|
||||
|
@ -426,9 +430,465 @@ static void EnumeratePhysicalDevices()
|
|||
|
||||
vkGetPhysicalDeviceMemoryProperties( gpu.device, &gpu.memProps );
|
||||
vkGetPhysicalDeviceProperties( gpu.device, &gpu.props );
|
||||
|
||||
switch( gpu.props.vendorID )
|
||||
{
|
||||
case 0x8086:
|
||||
idLib::Printf( "Found device[%i] Vendor: Intel\n", i );
|
||||
break;
|
||||
|
||||
case 0x10DE:
|
||||
idLib::Printf( "Found device[%i] Vendor: NVIDIA\n", i );
|
||||
break;
|
||||
|
||||
case 0x1002:
|
||||
idLib::Printf( "Found device[%i] Vendor: AMD\n", i );
|
||||
break;
|
||||
|
||||
default:
|
||||
idLib::Printf( "Found device[%i] Vendor: Unknown (0x%x)\n", i, gpu.props.vendorID );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=============
|
||||
CheckPhysicalDeviceExtensionSupport
|
||||
=============
|
||||
*/
|
||||
static bool CheckPhysicalDeviceExtensionSupport( gpuInfo_t& gpu, idList< const char* >& requiredExt )
|
||||
{
|
||||
int required = requiredExt.Num();
|
||||
int available = 0;
|
||||
|
||||
for( int i = 0; i < requiredExt.Num(); ++i )
|
||||
{
|
||||
for( int j = 0; j < gpu.extensionProps.Num(); ++j )
|
||||
{
|
||||
if( idStr::Icmp( requiredExt[ i ], gpu.extensionProps[ j ].extensionName ) == 0 )
|
||||
{
|
||||
available++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return available == required;
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
SelectPhysicalDevice
|
||||
=============
|
||||
*/
|
||||
static void SelectPhysicalDevice()
|
||||
{
|
||||
//idLib::Printf( "Selecting physical device:\n" );
|
||||
|
||||
for( int i = 0; i < vkcontext.gpus.Num(); ++i )
|
||||
{
|
||||
gpuInfo_t& gpu = vkcontext.gpus[ i ];
|
||||
|
||||
int graphicsIdx = -1;
|
||||
int presentIdx = -1;
|
||||
|
||||
if( !CheckPhysicalDeviceExtensionSupport( gpu, vkcontext.deviceExtensions ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if( gpu.surfaceFormats.Num() == 0 )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if( gpu.presentModes.Num() == 0 )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Find graphics queue family
|
||||
for( int j = 0; j < gpu.queueFamilyProps.Num(); ++j )
|
||||
{
|
||||
VkQueueFamilyProperties& props = gpu.queueFamilyProps[ j ];
|
||||
|
||||
if( props.queueCount == 0 )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if( props.queueFlags & VK_QUEUE_GRAPHICS_BIT )
|
||||
{
|
||||
graphicsIdx = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Find present queue family
|
||||
for( int j = 0; j < gpu.queueFamilyProps.Num(); ++j )
|
||||
{
|
||||
VkQueueFamilyProperties& props = gpu.queueFamilyProps[ j ];
|
||||
|
||||
if( props.queueCount == 0 )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
VkBool32 supportsPresent = VK_FALSE;
|
||||
vkGetPhysicalDeviceSurfaceSupportKHR( gpu.device, j, vkcontext.surface, &supportsPresent );
|
||||
if( supportsPresent )
|
||||
{
|
||||
presentIdx = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Did we find a device supporting both graphics and present.
|
||||
if( graphicsIdx >= 0 && presentIdx >= 0 )
|
||||
{
|
||||
vkcontext.graphicsFamilyIdx = graphicsIdx;
|
||||
vkcontext.presentFamilyIdx = presentIdx;
|
||||
vkcontext.physicalDevice = gpu.device;
|
||||
vkcontext.gpu = &gpu;
|
||||
|
||||
vkGetPhysicalDeviceFeatures( vkcontext.physicalDevice, &vkcontext.physicalDeviceFeatures );
|
||||
|
||||
idLib::Printf( "Selected device '%s'\n", gpu.props.deviceName );
|
||||
|
||||
// RB: found vendor IDs in nvQuake
|
||||
switch( gpu.props.vendorID )
|
||||
{
|
||||
case 0x8086:
|
||||
idLib::Printf( "Vendor: Intel\n", i );
|
||||
glConfig.vendor = VENDOR_INTEL;
|
||||
break;
|
||||
|
||||
case 0x10DE:
|
||||
idLib::Printf( "Vendor: NVIDIA\n", i );
|
||||
glConfig.vendor = VENDOR_NVIDIA;
|
||||
break;
|
||||
|
||||
case 0x1002:
|
||||
idLib::Printf( "Vendor: AMD\n", i );
|
||||
glConfig.vendor = VENDOR_AMD;
|
||||
break;
|
||||
|
||||
default:
|
||||
idLib::Printf( "Vendor: Unknown (0x%x)\n", i, gpu.props.vendorID );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// If we can't render or present, just bail.
|
||||
idLib::FatalError( "Could not find a physical device which fits our desired profile" );
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
CreateLogicalDeviceAndQueues
|
||||
=============
|
||||
*/
|
||||
static void CreateLogicalDeviceAndQueues()
|
||||
{
|
||||
idList< int > uniqueIdx;
|
||||
uniqueIdx.AddUnique( vkcontext.graphicsFamilyIdx );
|
||||
uniqueIdx.AddUnique( vkcontext.presentFamilyIdx );
|
||||
|
||||
idList< VkDeviceQueueCreateInfo > devqInfo;
|
||||
|
||||
const float priority = 1.0f;
|
||||
for( int i = 0; i < uniqueIdx.Num(); ++i )
|
||||
{
|
||||
VkDeviceQueueCreateInfo qinfo = {};
|
||||
qinfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
|
||||
qinfo.queueFamilyIndex = uniqueIdx[ i ];
|
||||
qinfo.queueCount = 1;
|
||||
qinfo.pQueuePriorities = &priority;
|
||||
|
||||
devqInfo.Append( qinfo );
|
||||
}
|
||||
|
||||
VkPhysicalDeviceFeatures deviceFeatures = {};
|
||||
deviceFeatures.textureCompressionBC = VK_TRUE;
|
||||
deviceFeatures.imageCubeArray = VK_TRUE;
|
||||
deviceFeatures.depthClamp = VK_TRUE;
|
||||
deviceFeatures.depthBiasClamp = VK_TRUE;
|
||||
deviceFeatures.depthBounds = VK_TRUE;
|
||||
deviceFeatures.fillModeNonSolid = VK_TRUE;
|
||||
deviceFeatures.samplerAnisotropy = vkcontext.physicalDeviceFeatures.samplerAnisotropy; // RB
|
||||
|
||||
VkDeviceCreateInfo info = {};
|
||||
info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
|
||||
info.queueCreateInfoCount = devqInfo.Num();
|
||||
info.pQueueCreateInfos = devqInfo.Ptr();
|
||||
info.pEnabledFeatures = &deviceFeatures;
|
||||
info.enabledExtensionCount = vkcontext.deviceExtensions.Num();
|
||||
info.ppEnabledExtensionNames = vkcontext.deviceExtensions.Ptr();
|
||||
|
||||
if( r_vkEnableValidationLayers.GetBool() )
|
||||
{
|
||||
info.enabledLayerCount = vkcontext.validationLayers.Num();
|
||||
info.ppEnabledLayerNames = vkcontext.validationLayers.Ptr();
|
||||
}
|
||||
else
|
||||
{
|
||||
info.enabledLayerCount = 0;
|
||||
}
|
||||
|
||||
ID_VK_CHECK( vkCreateDevice( vkcontext.physicalDevice, &info, NULL, &vkcontext.device ) );
|
||||
|
||||
vkGetDeviceQueue( vkcontext.device, vkcontext.graphicsFamilyIdx, 0, &vkcontext.graphicsQueue );
|
||||
vkGetDeviceQueue( vkcontext.device, vkcontext.presentFamilyIdx, 0, &vkcontext.presentQueue );
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
ChooseSurfaceFormat
|
||||
=============
|
||||
*/
|
||||
static VkSurfaceFormatKHR ChooseSurfaceFormat( idList< VkSurfaceFormatKHR >& formats )
|
||||
{
|
||||
VkSurfaceFormatKHR result;
|
||||
|
||||
if( formats.Num() == 1 && formats[ 0 ].format == VK_FORMAT_UNDEFINED )
|
||||
{
|
||||
result.format = VK_FORMAT_B8G8R8A8_UNORM;
|
||||
result.colorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR;
|
||||
return result;
|
||||
}
|
||||
|
||||
for( int i = 0; i < formats.Num(); ++i )
|
||||
{
|
||||
VkSurfaceFormatKHR& fmt = formats[ i ];
|
||||
if( fmt.format == VK_FORMAT_B8G8R8A8_UNORM && fmt.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR )
|
||||
{
|
||||
return fmt;
|
||||
}
|
||||
}
|
||||
|
||||
return formats[ 0 ];
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
ChoosePresentMode
|
||||
=============
|
||||
*/
|
||||
static VkPresentModeKHR ChoosePresentMode( idList< VkPresentModeKHR >& modes )
|
||||
{
|
||||
VkPresentModeKHR desiredMode = VK_PRESENT_MODE_FIFO_KHR;
|
||||
|
||||
if( r_swapInterval.GetInteger() < 1 )
|
||||
{
|
||||
for( int i = 0; i < modes.Num(); i++ )
|
||||
{
|
||||
if( modes[i] == VK_PRESENT_MODE_MAILBOX_KHR )
|
||||
{
|
||||
return VK_PRESENT_MODE_MAILBOX_KHR;
|
||||
}
|
||||
if( ( modes[i] != VK_PRESENT_MODE_MAILBOX_KHR ) && ( modes[i] == VK_PRESENT_MODE_IMMEDIATE_KHR ) )
|
||||
{
|
||||
return VK_PRESENT_MODE_IMMEDIATE_KHR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for( int i = 0; i < modes.Num(); ++i )
|
||||
{
|
||||
if( modes[i] == desiredMode )
|
||||
{
|
||||
return desiredMode;
|
||||
}
|
||||
}
|
||||
|
||||
return VK_PRESENT_MODE_FIFO_KHR;
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
ChooseSurfaceExtent
|
||||
=============
|
||||
*/
|
||||
static VkExtent2D ChooseSurfaceExtent( VkSurfaceCapabilitiesKHR& caps )
|
||||
{
|
||||
VkExtent2D extent;
|
||||
|
||||
if( caps.currentExtent.width == -1 )
|
||||
{
|
||||
extent.width = glConfig.nativeScreenWidth;
|
||||
extent.height = glConfig.nativeScreenHeight;
|
||||
}
|
||||
else
|
||||
{
|
||||
extent = caps.currentExtent;
|
||||
}
|
||||
|
||||
return extent;
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
CreateSwapChain
|
||||
=============
|
||||
*/
|
||||
static void CreateSwapChain()
|
||||
{
|
||||
gpuInfo_t& gpu = *vkcontext.gpu;
|
||||
|
||||
VkSurfaceFormatKHR surfaceFormat = ChooseSurfaceFormat( gpu.surfaceFormats );
|
||||
VkPresentModeKHR presentMode = ChoosePresentMode( gpu.presentModes );
|
||||
VkExtent2D extent = ChooseSurfaceExtent( gpu.surfaceCaps );
|
||||
|
||||
VkSwapchainCreateInfoKHR info = {};
|
||||
info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
|
||||
info.surface = vkcontext.surface;
|
||||
info.minImageCount = NUM_FRAME_DATA;
|
||||
info.imageFormat = surfaceFormat.format;
|
||||
info.imageColorSpace = surfaceFormat.colorSpace;
|
||||
info.imageExtent = extent;
|
||||
info.imageArrayLayers = 1;
|
||||
info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
|
||||
|
||||
if( vkcontext.graphicsFamilyIdx != vkcontext.presentFamilyIdx )
|
||||
{
|
||||
uint32 indices[] = { ( uint32 )vkcontext.graphicsFamilyIdx, ( uint32 )vkcontext.presentFamilyIdx };
|
||||
|
||||
info.imageSharingMode = VK_SHARING_MODE_CONCURRENT;
|
||||
info.queueFamilyIndexCount = 2;
|
||||
info.pQueueFamilyIndices = indices;
|
||||
}
|
||||
else
|
||||
{
|
||||
info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||
}
|
||||
|
||||
info.preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
|
||||
info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
|
||||
info.presentMode = presentMode;
|
||||
info.clipped = VK_TRUE;
|
||||
|
||||
ID_VK_CHECK( vkCreateSwapchainKHR( vkcontext.device, &info, NULL, &vkcontext.swapchain ) );
|
||||
|
||||
vkcontext.swapchainFormat = surfaceFormat.format;
|
||||
vkcontext.presentMode = presentMode;
|
||||
vkcontext.swapchainExtent = extent;
|
||||
vkcontext.fullscreen = glConfig.isFullscreen;
|
||||
|
||||
uint32 numImages = 0;
|
||||
idArray< VkImage, NUM_FRAME_DATA > swapchainImages;
|
||||
ID_VK_CHECK( vkGetSwapchainImagesKHR( vkcontext.device, vkcontext.swapchain, &numImages, NULL ) );
|
||||
ID_VK_VALIDATE( numImages > 0, "vkGetSwapchainImagesKHR returned a zero image count." );
|
||||
|
||||
ID_VK_CHECK( vkGetSwapchainImagesKHR( vkcontext.device, vkcontext.swapchain, &numImages, swapchainImages.Ptr() ) );
|
||||
ID_VK_VALIDATE( numImages > 0, "vkGetSwapchainImagesKHR returned a zero image count." );
|
||||
|
||||
for( uint32 i = 0; i < NUM_FRAME_DATA; ++i )
|
||||
{
|
||||
VkImageViewCreateInfo imageViewCreateInfo = {};
|
||||
imageViewCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
||||
imageViewCreateInfo.image = swapchainImages[ i ];
|
||||
imageViewCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
||||
imageViewCreateInfo.format = vkcontext.swapchainFormat;
|
||||
imageViewCreateInfo.components.r = VK_COMPONENT_SWIZZLE_R;
|
||||
imageViewCreateInfo.components.g = VK_COMPONENT_SWIZZLE_G;
|
||||
imageViewCreateInfo.components.b = VK_COMPONENT_SWIZZLE_B;
|
||||
imageViewCreateInfo.components.a = VK_COMPONENT_SWIZZLE_A;
|
||||
imageViewCreateInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
imageViewCreateInfo.subresourceRange.baseMipLevel = 0;
|
||||
imageViewCreateInfo.subresourceRange.levelCount = 1;
|
||||
imageViewCreateInfo.subresourceRange.baseArrayLayer = 0;
|
||||
imageViewCreateInfo.subresourceRange.layerCount = 1;
|
||||
imageViewCreateInfo.flags = 0;
|
||||
|
||||
VkImageView imageView;
|
||||
ID_VK_CHECK( vkCreateImageView( vkcontext.device, &imageViewCreateInfo, NULL, &imageView ) );
|
||||
|
||||
idImage* image = new idImage( va( "_swapchain%d", i ) );
|
||||
image->CreateFromSwapImage(
|
||||
swapchainImages[ i ],
|
||||
imageView,
|
||||
vkcontext.swapchainFormat,
|
||||
vkcontext.swapchainExtent );
|
||||
vkcontext.swapchainImages[ i ] = image;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
CreateCommandPool
|
||||
=============
|
||||
*/
|
||||
static void CreateCommandPool()
|
||||
{
|
||||
VkCommandPoolCreateInfo commandPoolCreateInfo = {};
|
||||
commandPoolCreateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
|
||||
commandPoolCreateInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
|
||||
commandPoolCreateInfo.queueFamilyIndex = vkcontext.graphicsFamilyIdx;
|
||||
|
||||
ID_VK_CHECK( vkCreateCommandPool( vkcontext.device, &commandPoolCreateInfo, NULL, &vkcontext.commandPool ) );
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
CreateCommandBuffer
|
||||
=============
|
||||
*/
|
||||
static void CreateCommandBuffer()
|
||||
{
|
||||
VkCommandBufferAllocateInfo commandBufferAllocateInfo = {};
|
||||
commandBufferAllocateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
|
||||
commandBufferAllocateInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
|
||||
commandBufferAllocateInfo.commandPool = vkcontext.commandPool;
|
||||
commandBufferAllocateInfo.commandBufferCount = NUM_FRAME_DATA;
|
||||
|
||||
ID_VK_CHECK( vkAllocateCommandBuffers( vkcontext.device, &commandBufferAllocateInfo, vkcontext.commandBuffer.Ptr() ) );
|
||||
|
||||
VkFenceCreateInfo fenceCreateInfo = {};
|
||||
fenceCreateInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
|
||||
|
||||
for( int i = 0; i < NUM_FRAME_DATA; ++i )
|
||||
{
|
||||
ID_VK_CHECK( vkCreateFence( vkcontext.device, &fenceCreateInfo, NULL, &vkcontext.commandBufferFences[ i ] ) );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
CreateSemaphores
|
||||
=============
|
||||
*/
|
||||
static void CreateSemaphores()
|
||||
{
|
||||
VkSemaphoreCreateInfo semaphoreCreateInfo = {};
|
||||
semaphoreCreateInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
|
||||
|
||||
for( int i = 0; i < NUM_FRAME_DATA; ++i )
|
||||
{
|
||||
ID_VK_CHECK( vkCreateSemaphore( vkcontext.device, &semaphoreCreateInfo, NULL, &vkcontext.acquireSemaphores[ i ] ) );
|
||||
ID_VK_CHECK( vkCreateSemaphore( vkcontext.device, &semaphoreCreateInfo, NULL, &vkcontext.renderCompleteSemaphores[ i ] ) );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
DestroySwapChain
|
||||
=============
|
||||
*/
|
||||
static void DestroySwapChain()
|
||||
{
|
||||
for( uint32 i = 0; i < NUM_FRAME_DATA; ++i )
|
||||
{
|
||||
vkDestroyImageView( vkcontext.device, vkcontext.swapchainImages[ i ]->GetView(), NULL );
|
||||
delete vkcontext.swapchainImages[ i ];
|
||||
}
|
||||
vkcontext.swapchainImages.Zero();
|
||||
|
||||
vkDestroySwapchainKHR( vkcontext.device, vkcontext.swapchain, NULL );
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
ClearContext
|
||||
|
@ -498,17 +958,6 @@ idRenderBackend::~idRenderBackend()
|
|||
|
||||
}
|
||||
|
||||
/*
|
||||
=============================
|
||||
R_IsInitialized
|
||||
=============================
|
||||
*/
|
||||
static bool r_initialized = false;
|
||||
bool R_IsInitialized()
|
||||
{
|
||||
return r_initialized;
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
idRenderBackend::Init
|
||||
|
@ -516,7 +965,7 @@ idRenderBackend::Init
|
|||
*/
|
||||
void idRenderBackend::Init()
|
||||
{
|
||||
if( R_IsInitialized() )
|
||||
if( tr.IsInitialized() )
|
||||
{
|
||||
idLib::FatalError( "R_InitVulkan called while active" );
|
||||
}
|
||||
|
@ -542,6 +991,64 @@ void idRenderBackend::Init()
|
|||
|
||||
// grab detailed information of available GPUs
|
||||
EnumeratePhysicalDevices();
|
||||
|
||||
// find queue family/families supporting graphics and present.
|
||||
SelectPhysicalDevice();
|
||||
|
||||
// create logical device and queues
|
||||
CreateLogicalDeviceAndQueues();
|
||||
|
||||
// create semaphores for image acquisition and rendering completion
|
||||
CreateSemaphores();
|
||||
|
||||
// create Command Pool
|
||||
CreateCommandPool();
|
||||
|
||||
// create Command Buffer
|
||||
CreateCommandBuffer();
|
||||
|
||||
// setup the allocator
|
||||
#if defined( USE_AMD_ALLOCATOR )
|
||||
extern idCVar r_vkHostVisibleMemoryMB;
|
||||
extern idCVar r_vkDeviceLocalMemoryMB;
|
||||
|
||||
VmaAllocatorCreateInfo createInfo = {};
|
||||
createInfo.physicalDevice = vkcontext.physicalDevice;
|
||||
createInfo.device = vkcontext.device;
|
||||
createInfo.preferredSmallHeapBlockSize = r_vkHostVisibleMemoryMB.GetInteger() * 1024 * 1024;
|
||||
createInfo.preferredLargeHeapBlockSize = r_vkDeviceLocalMemoryMB.GetInteger() * 1024 * 1024;
|
||||
|
||||
vmaCreateAllocator( &createInfo, &vmaAllocator );
|
||||
#else
|
||||
vulkanAllocator.Init();
|
||||
#endif
|
||||
|
||||
// start the Staging Manager
|
||||
stagingManager.Init();
|
||||
|
||||
// create Swap Chain
|
||||
CreateSwapChain();
|
||||
|
||||
#if 0
|
||||
|
||||
// create Render Targets
|
||||
CreateRenderTargets();
|
||||
|
||||
// create Render Pass
|
||||
CreateRenderPass();
|
||||
|
||||
// create Pipeline Cache
|
||||
CreatePipelineCache();
|
||||
|
||||
// create Frame Buffers
|
||||
CreateFrameBuffers();
|
||||
|
||||
// init RenderProg Manager
|
||||
renderProgManager.Init();
|
||||
#endif
|
||||
|
||||
// init Vertex Cache
|
||||
vertexCache.Init( vkcontext.gpu->props.limits.minUniformBufferOffsetAlignment );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -551,18 +1058,60 @@ idRenderBackend::Shutdown
|
|||
*/
|
||||
void idRenderBackend::Shutdown()
|
||||
{
|
||||
for( int i = 0; i < NUM_FRAME_DATA; ++i )
|
||||
{
|
||||
idImage::EmptyGarbage();
|
||||
}
|
||||
|
||||
// destroy Swap Chain
|
||||
DestroySwapChain();
|
||||
|
||||
// stop the Staging Manager
|
||||
stagingManager.Shutdown();
|
||||
|
||||
// destroy Command Buffer
|
||||
vkFreeCommandBuffers( vkcontext.device, vkcontext.commandPool, NUM_FRAME_DATA, vkcontext.commandBuffer.Ptr() );
|
||||
for( int i = 0; i < NUM_FRAME_DATA; ++i )
|
||||
{
|
||||
vkDestroyFence( vkcontext.device, vkcontext.commandBufferFences[ i ], NULL );
|
||||
}
|
||||
|
||||
// destroy Command Pool
|
||||
vkDestroyCommandPool( vkcontext.device, vkcontext.commandPool, NULL );
|
||||
|
||||
// destroy Semaphores
|
||||
for( int i = 0; i < NUM_FRAME_DATA; ++i )
|
||||
{
|
||||
vkDestroySemaphore( vkcontext.device, vkcontext.acquireSemaphores[ i ], NULL );
|
||||
vkDestroySemaphore( vkcontext.device, vkcontext.renderCompleteSemaphores[ i ], NULL );
|
||||
}
|
||||
|
||||
// destroy Debug Callback
|
||||
if( r_vkEnableValidationLayers.GetBool() )
|
||||
{
|
||||
DestroyDebugReportCallback();
|
||||
}
|
||||
|
||||
// dump all our memory
|
||||
#if defined( USE_AMD_ALLOCATOR )
|
||||
vmaDestroyAllocator( vmaAllocator );
|
||||
#else
|
||||
vulkanAllocator.Shutdown();
|
||||
#endif
|
||||
|
||||
// destroy Logical Device
|
||||
vkDestroyDevice( vkcontext.device, NULL );
|
||||
|
||||
// destroy Surface
|
||||
vkDestroySurfaceKHR( vkcontext.instance, vkcontext.surface, NULL );
|
||||
|
||||
// destroy the Instance
|
||||
vkDestroyInstance( vkcontext.instance, NULL );
|
||||
|
||||
ClearContext();
|
||||
|
||||
// destroy main window
|
||||
GLimp_Shutdown();
|
||||
r_initialized = false;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
Doom 3 BFG Edition GPL Source Code
|
||||
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
|
||||
Copyright (C) 2016-2017 Dustin Land
|
||||
|
||||
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
|
||||
|
||||
|
|
|
@ -97,7 +97,7 @@ static void WIN_EnableAltTab()
|
|||
|
||||
void WIN_Sizing( WORD side, RECT* rect )
|
||||
{
|
||||
if( !R_IsInitialized() || renderSystem->GetWidth() <= 0 || renderSystem->GetHeight() <= 0 )
|
||||
if( !renderSystem->IsInitialized() || renderSystem->GetWidth() <= 0 || renderSystem->GetHeight() <= 0 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -176,7 +176,7 @@ LONG WINAPI MainWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
|
|||
switch( uMsg )
|
||||
{
|
||||
case WM_WINDOWPOSCHANGED:
|
||||
if( R_IsInitialized() )
|
||||
if( renderSystem->IsInitialized() )
|
||||
{
|
||||
RECT rect;
|
||||
if( ::GetClientRect( win32.hWnd, &rect ) )
|
||||
|
|
Loading…
Reference in a new issue