diff --git a/source/qcore/qtypes.h b/source/qcore/qtypes.h index 1260d986d9..52d095cdb1 100644 --- a/source/qcore/qtypes.h +++ b/source/qcore/qtypes.h @@ -47,6 +47,10 @@ #include +#define KB_TO_BYTE (1024) +#define MB_TO_BYTE (1024 * KB_TO_BYTE) +#define GB_TO_BYTE (1024 * MB_TO_BYTE) + #if INTPTR_MAX == 0x7FFFFFFFFFFFFFFFLL #define Q_PTR_SIZE 8 #elif INTPTR_MAX == 0x7FFFFFFF diff --git a/source/ref_nri/r_frame_cmd_buffer.h b/source/ref_nri/r_frame_cmd_buffer.h index 2c968f21b7..f86b13595a 100644 --- a/source/ref_nri/r_frame_cmd_buffer.h +++ b/source/ref_nri/r_frame_cmd_buffer.h @@ -15,8 +15,9 @@ #include "r_graphics.h" #include "qhash.h" +#include "ri_format.h" -#define POGO_BUFFER_TEXTURE_FORMAT NriFormat_RGBA8_UNORM +#define POGO_BUFFER_TEXTURE_FORMAT RI_FORMAT_RGBA8_UNORM typedef struct mesh_vbo_s mesh_vbo_t; typedef struct mfog_s mfog_t; @@ -106,12 +107,10 @@ struct frame_tex_buffers_s { NriDescriptor *colorAttachment; NriTexture *colorTexture; - struct RITexture_s* riColorTexture; - NriDescriptor *depthAttachment; NriTexture* depthTexture; - struct RITexture_s* riDepthTexture; + struct RITextureHandle_s* riDepthTexture; // used for post processing struct pogo_buffers_s { @@ -149,7 +148,7 @@ struct frame_cmd_buffer_s { } vk; #endif }; - struct RICmd_s command; + struct RICmdHandle_s command; uint64_t frameCount; // this value is bound by NUMBER_FRAMES_FLIGHT struct block_buffer_pool_s uboBlockBuffer; diff --git a/source/ref_nri/r_frontend.c b/source/ref_nri/r_frontend.c index a2e5e6fd61..0524c9eeb5 100644 --- a/source/ref_nri/r_frontend.c +++ b/source/ref_nri/r_frontend.c @@ -176,7 +176,7 @@ rserr_t RF_Init( const char *applicationName, const char *screenshotPrefix, int }; rsh.shadowSamplerDescriptor = R_CreateDescriptorWrapper( &rsh.nri, R_ResolveSamplerDescriptor( IT_DEPTHCOMPARE | IT_SPECIAL | IT_DEPTH ) ); - GPU_VULKAN_BLOCK( renderer, ( { + GPU_VULKAN_BLOCK( (&rsh.renderer), ( { for( size_t i = 0; i < NUMBER_FRAMES_FLIGHT; i++ ) { VkCommandPoolCreateInfo commandPoolInfo = { VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO }; commandPoolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; @@ -191,11 +191,11 @@ rserr_t RF_Init( const char *applicationName, const char *screenshotPrefix, int info.commandPool = rsh.frameCmds[i].vk.pool; info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; info.commandBufferCount = 1; - result = vkAllocateCommandBuffers( rsh.device.vk.device, &info, &rsh.frameCmds[i].command.vk.cmd ); - if( result != VK_SUCCESS ) { - Com_Printf( "Vulkan failed error - vk: %d", result ); - return rserr_unknown; - } + // result = vkAllocateCommandBuffers( rsh.device.vk.device, &info, &rsh.frameCmds[i].command.vk.cmd ); + // if( result != VK_SUCCESS ) { + // Com_Printf( "Vulkan failed error - vk: %d", result ); + // return rserr_unknown; + // } InitBlockBufferPool( &rsh.nri, &rsh.frameCmds[i].uboBlockBuffer, &uboBlockBufferDesc ); } })); @@ -264,29 +264,21 @@ rserr_t RF_SetMode( int x, int y, int width, int height, int displayFrequency, b { struct RIWindowHandle_s windowHandle = {}; - NriWindow nriWindow = { 0 }; switch( handle.winType ) { case VID_WINDOW_WAYLAND: windowHandle.type = RI_WINDOW_WAYLAND; windowHandle.wayland.surface = handle.window.wayland.surface; windowHandle.wayland.display = handle.window.wayland.display; - nriWindow.wayland.surface = handle.window.wayland.surface; - nriWindow.wayland.display = handle.window.wayland.display; break; case VID_WINDOW_TYPE_X11: windowHandle.type = RI_WINDOW_X11; windowHandle.x11.window = handle.window.x11.window; windowHandle.x11.dpy = handle.window.x11.dpy; - - nriWindow.x11.window = handle.window.x11.window; - nriWindow.x11.dpy = handle.window.x11.dpy; break; case VID_WINDOW_WIN32: windowHandle.type = RI_WINDOW_WIN32; windowHandle.windows.hwnd = handle.window.win.hwnd; - - nriWindow.windows.hwnd = handle.window.win.hwnd; break; default: assert( false ); @@ -301,10 +293,54 @@ rserr_t RF_SetMode( int x, int y, int width, int height, int displayFrequency, b swapchainInit.format = RI_SWAPCHAIN_BT709_G22_8BIT; InitRISwapchain(&rsh.device, &swapchainInit, &rsh.riSwapchain); + GPU_VULKAN_BLOCK( ( &rsh.renderer ), ({ + uint32_t queueFamilies[RI_QUEUE_LEN] = { 0 }; + VkImageCreateInfo info = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO }; + VkImageCreateFlags flags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT | VK_IMAGE_CREATE_EXTENDED_USAGE_BIT; // typeless + info.flags = flags; + info.imageType = VK_IMAGE_TYPE_2D; + info.extent.width = rsh.riSwapchain.width; + info.extent.height = rsh.riSwapchain.height; + info.extent.depth = 1; + info.mipLevels = 1; + info.arrayLayers = 1; + info.samples = 1; + info.tiling = VK_IMAGE_TILING_OPTIMAL; + info.pQueueFamilyIndices = queueFamilies; + vk_fillQueueFamilies( &rsh.device, queueFamilies, &info.queueFamilyIndexCount, RI_QUEUE_LEN ); + info.sharingMode = ( info.queueFamilyIndexCount > 0 ) ? VK_SHARING_MODE_CONCURRENT : VK_SHARING_MODE_EXCLUSIVE; // TODO: still no DCC on AMD with concurrent? + info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + + VkImageViewUsageCreateInfo usageInfo = { VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO }; + usageInfo.usage |= VK_IMAGE_USAGE_SAMPLED_BIT; + VkImageSubresourceRange subresource = { + VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1, + }; + VkImageViewCreateInfo createInfo = { VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO }; + createInfo.pNext = &usageInfo; + createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; + createInfo.format = info.format; + createInfo.subresourceRange = subresource; + + for( uint32_t i = 0; i < NUMBER_FRAMES_FLIGHT; i++ ) { + info.format = RIFormatToVK( POGO_BUFFER_TEXTURE_FORMAT ); + if( VK_WrapResult( vkCreateImage( rsh.device.vk.device, &info, NULL, &rsh.vk.pogo[( i * 2 )] ) ) ) { + } + if( VK_WrapResult( vkCreateImage( rsh.device.vk.device, &info, NULL, &rsh.vk.pogo[( i * 2 ) + 1] ) ) ) { + } + info.format = RIFormatToVK( RI_FORMAT_D32_SFLOAT ); + if( VK_WrapResult( vkCreateImage( rsh.device.vk.device, &info, NULL, &rsh.vk.depthImages[i] ) ) ) { + } + + createInfo.image = rsh.vk.depthImages[i]; + RI_VK_InitImageView(&rsh.device, &createInfo, rsh.vk.depthAttachment + i ); + } + })); + arrsetlen( rsh.backBuffers, rsh.riSwapchain.imageCount); - for( uint32_t i = 0; i < rsh.riSwapchain.imageCount; i++ ) { - rsh.backBuffers[i].riColorTexture = rsh.riSwapchain.images + i; - } + //for( uint32_t i = 0; i < rsh.riSwapchain.imageCount; i++ ) { + // rsh.backBuffers[i].riColorTexture = rsh.riSwapchain.images + i; + //} NriSwapChainDesc swapChainDesc = { @@ -312,8 +348,7 @@ rserr_t RF_SetMode( int x, int y, int width, int height, int displayFrequency, b .width = width, .height = height, .format = DefaultSwapchainFormat, - .textureNum = 3, - .window = nriWindow }; + .textureNum = 3 }; __ShutdownSwapchainTexture(); assert(rsh.frameFence == NULL); diff --git a/source/ref_nri/r_image.c b/source/ref_nri/r_image.c index c825c50a10..6e54b008d9 100644 --- a/source/ref_nri/r_image.c +++ b/source/ref_nri/r_image.c @@ -38,16 +38,18 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "r_ktx_loader.h" #include - #include +#include "ri_types.h" +#include "ri_format.h" + #define MAX_GLIMAGES 8192 #define IMAGES_HASH_SIZE 64 #define IMAGE_SAMPLER_HASH_SIZE 1024 static struct { hash_t hash; - NriDescriptor *descriptor; + struct RIDescriptor_s descriptor; } samplerDescriptors[IMAGE_SAMPLER_HASH_SIZE] = {0}; typedef struct @@ -61,9 +63,14 @@ static struct image_s images_hash_headnode[IMAGES_HASH_SIZE], *free_images; static qmutex_t *r_imagesLock; static mempool_t *r_imagesPool; -static int defaultFilterMin = NriFilter_NEAREST; -static int defaultFilterMag = NriFilter_NEAREST; -static int defaultFilterMipMap = NriFilter_LINEAR; +enum ImageFilter{ + IMAGE_FILTER_NEAREST, + IMAGE_FILTER_LINEAR, +}; + +static int defaultFilterMin = IMAGE_FILTER_NEAREST; +static int defaultFilterMag = IMAGE_FILTER_NEAREST; +static int defaultFilterMipMap = IMAGE_FILTER_LINEAR; static int defaultAnisotropicFilter = 0; #define MAX_MIP_SAMPLES 16 @@ -106,61 +113,64 @@ static void __FreeGPUImageData( struct frame_cmd_buffer_s *cmd, struct image_s * image->samplerDescriptor = ( struct nri_descriptor_s ){ 0 }; } -NriDescriptor *R_ResolveSamplerDescriptor( int flags ) +struct RIDescriptor_s *R_ResolveSamplerDescriptor( int flags ) { - - NriSamplerDesc samplerDesc = {0}; - - if( flags & IT_NOFILTERING ) { - samplerDesc.filters.min = NriFilter_LINEAR; - samplerDesc.filters.mag = NriFilter_LINEAR; - samplerDesc.filters.mip = NriFilter_LINEAR; - } else if( flags & IT_DEPTH ) { - samplerDesc.filters.min = NriFilter_LINEAR; - samplerDesc.filters.mag = NriFilter_LINEAR; - samplerDesc.filters.mip = NriFilter_LINEAR; - samplerDesc.anisotropy = defaultAnisotropicFilter; - } else if( !( flags & IT_NOMIPMAP ) ) { - samplerDesc.filters.min = defaultFilterMin; - samplerDesc.filters.mag = defaultFilterMag; - samplerDesc.filters.mip = defaultFilterMipMap; - samplerDesc.mipMax = 16; - samplerDesc.anisotropy = defaultAnisotropicFilter; - } else { - samplerDesc.filters.min = NriFilter_LINEAR; - samplerDesc.filters.mag = NriFilter_LINEAR; - samplerDesc.filters.mip = NriFilter_LINEAR; - samplerDesc.anisotropy = defaultAnisotropicFilter; - } - - if( flags & IT_CLAMP ) { - samplerDesc.addressModes.u = NriAddressMode_CLAMP_TO_EDGE; - samplerDesc.addressModes.v = NriAddressMode_CLAMP_TO_EDGE; - samplerDesc.addressModes.w = NriAddressMode_CLAMP_TO_EDGE; - } - - if( ( flags & IT_DEPTH ) && ( flags & IT_DEPTHCOMPARE ) ) { - samplerDesc.compareFunc = NriCompareFunc_LESS_EQUAL; - } - - const hash_t hash = hash_data( HASH_INITIAL_VALUE, &samplerDesc, sizeof( NriSamplerDesc ) ); - const size_t startIndex = ( hash % IMAGE_SAMPLER_HASH_SIZE ); - size_t index = startIndex; - - do { - if( samplerDescriptors[index].hash == hash ) { - return samplerDescriptors[index].descriptor; - } else if( samplerDescriptors[index].descriptor == NULL ) { - samplerDescriptors[index].hash = hash; - rsh.nri.coreI.CreateSampler( rsh.nri.device, &samplerDesc, &samplerDescriptors[index].descriptor ); - return samplerDescriptors[index].descriptor; - } - index = ( index + 1 ) % IMAGE_SAMPLER_HASH_SIZE ; - } while( index != startIndex ); + GPU_VULKAN_BLOCK( ( &rsh.renderer ), ( { + VkSamplerCreateInfo info = { VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO }; + if( flags & IT_NOFILTERING ) { + info.minFilter = VK_FILTER_LINEAR; + info.magFilter = VK_FILTER_LINEAR; + info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; + } else if( flags & IT_DEPTH ) { + info.minFilter = VK_FILTER_LINEAR; + info.magFilter = VK_FILTER_LINEAR; + info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; + info.maxAnisotropy = defaultAnisotropicFilter; + info.anisotropyEnable = defaultAnisotropicFilter > 1.0f; + } else if( !( flags & IT_NOMIPMAP ) ) { + VkFilter filterMapping[] = { [IMAGE_FILTER_LINEAR] = VK_FILTER_LINEAR, [IMAGE_FILTER_NEAREST] = VK_FILTER_NEAREST }; + VkSamplerMipmapMode mapMapFilterMapping[] = { [IMAGE_FILTER_LINEAR] = VK_SAMPLER_MIPMAP_MODE_LINEAR, [IMAGE_FILTER_NEAREST] = VK_SAMPLER_MIPMAP_MODE_NEAREST }; + info.minFilter = filterMapping[defaultFilterMin]; + info.magFilter = filterMapping[defaultFilterMag]; + info.mipmapMode = mapMapFilterMapping[defaultFilterMipMap]; + info.maxLod = 16; + info.maxAnisotropy = defaultAnisotropicFilter; + info.anisotropyEnable = defaultAnisotropicFilter > 1.0f; + } else { + info.minFilter = VK_FILTER_LINEAR; + info.magFilter = VK_FILTER_LINEAR; + info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; + info.maxAnisotropy = defaultAnisotropicFilter; + info.anisotropyEnable = defaultAnisotropicFilter > 1.0f; + } + + if( flags & IT_CLAMP ) { + info.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + info.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + info.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + } + if( ( flags & IT_DEPTH ) && ( flags & IT_DEPTHCOMPARE ) ) { + info.compareOp = VK_COMPARE_OP_LESS_OR_EQUAL; + info.compareEnable = 1; + } + const hash_t hash = hash_data( HASH_INITIAL_VALUE, &info, sizeof( VkSamplerCreateInfo ) ); + const size_t startIndex = ( hash % IMAGE_SAMPLER_HASH_SIZE ); + size_t index = startIndex; + + do { + if( samplerDescriptors[index].hash == hash ) { + return &samplerDescriptors[index].descriptor; + } else if( IsEmptyDescriptor( &rsh.device, &samplerDescriptors[index].descriptor ) ) { + samplerDescriptors[index].hash = hash; + RI_VK_InitSampler( &rsh.device, &info, &samplerDescriptors[index].descriptor ); + return &samplerDescriptors[index].descriptor; + } + index = ( index + 1 ) % IMAGE_SAMPLER_HASH_SIZE; + } while( index != startIndex ); + } ) ); return NULL; } - #undef __SAMPLER_HASH_SIZE @@ -175,7 +185,7 @@ static void __RefreshSamplerDescriptors() { if( (glt->flags & (IT_NOFILTERING | IT_NOMIPMAP)) ) { continue; } - glt->samplerDescriptor = R_CreateDescriptorWrapper(&rsh.nri, R_ResolveSamplerDescriptor(glt->flags)); + glt->samplerBinding = R_ResolveSamplerDescriptor( glt->flags ); } } @@ -184,13 +194,13 @@ void R_TextureMode( char *string ) { static struct { char *name; - NriFilter min, mag, mip; - } modes[] = { { "GL_NEAREST", NriFilter_NEAREST, NriFilter_NEAREST, NriFilter_LINEAR}, - { "GL_LINEAR", NriFilter_LINEAR, NriFilter_LINEAR, NriFilter_LINEAR}, - { "GL_NEAREST_MIPMAP_NEAREST", NriFilter_NEAREST, NriFilter_NEAREST, NriFilter_NEAREST}, - { "GL_LINEAR_MIPMAP_NEAREST", NriFilter_LINEAR, NriFilter_LINEAR, NriFilter_NEAREST}, - { "GL_NEAREST_MIPMAP_LINEAR", NriFilter_NEAREST, NriFilter_NEAREST, NriFilter_LINEAR }, - { "GL_LINEAR_MIPMAP_LINEAR", NriFilter_LINEAR, NriFilter_LINEAR, NriFilter_LINEAR } }; + int min, mag, mip; + } modes[] = { { "GL_NEAREST", IMAGE_FILTER_NEAREST, IMAGE_FILTER_NEAREST, IMAGE_FILTER_LINEAR}, + { "GL_LINEAR", IMAGE_FILTER_LINEAR, IMAGE_FILTER_LINEAR, IMAGE_FILTER_LINEAR}, + { "GL_NEAREST_MIPMAP_NEAREST", IMAGE_FILTER_NEAREST, IMAGE_FILTER_NEAREST, IMAGE_FILTER_NEAREST}, + { "GL_LINEAR_MIPMAP_NEAREST", IMAGE_FILTER_LINEAR, IMAGE_FILTER_LINEAR, IMAGE_FILTER_NEAREST}, + { "GL_NEAREST_MIPMAP_LINEAR", IMAGE_FILTER_NEAREST, IMAGE_FILTER_NEAREST, IMAGE_FILTER_LINEAR }, + { "GL_LINEAR_MIPMAP_LINEAR", IMAGE_FILTER_LINEAR, IMAGE_FILTER_LINEAR, IMAGE_FILTER_LINEAR } }; size_t i = 0; for(i = 0; i < Q_ARRAY_COUNT(modes); i++) { @@ -212,8 +222,7 @@ void R_TextureMode( char *string ) void R_AnisotropicFilter( int value ) { - const NriDeviceDesc *desc = rsh.nri.coreI.GetDeviceDesc( rsh.nri.device ); - defaultAnisotropicFilter = bound( 1, value, desc->samplerAnisotropyMax ); + defaultAnisotropicFilter = bound( 1, value, rsh.device.physicalAdapter.samplerAnisotropyMax ); __RefreshSamplerDescriptors(); } @@ -336,20 +345,6 @@ void R_FreeImageBuffers( void ) } } -/* -* R_EndianSwap16BitImage -*/ -static void R_EndianSwap16BitImage( unsigned short *data, int width, int height ) -{ - int i; - while( height-- > 0 ) - { - for( i = 0; i < width; i++, data++ ) - *data = ( ( *data & 255 ) << 8 ) | ( *data >> 8 ); - data += width & 1; // 4 unpack alignment - } -} - /* * R_AllocImageBufferCb */ @@ -358,7 +353,6 @@ static uint8_t *_R_AllocImageBufferCb( void *ptr, size_t size, const char *filen loaderCbInfo_t *cbinfo = ptr; return _R_PrepareImageBuffer( cbinfo->ctx, cbinfo->side, size, filename, linenum ); } -\ static void __R_stbi_free_image(void* p) { stbi_uc* img = (stbi_uc*) p; @@ -769,48 +763,91 @@ static bool __R_LoadKTX( image_t *image, const char *pathname ) const uint32_t numberOfFaces = R_KTXGetNumberFaces( &ktxContext ); const uint16_t minMipSize = __R_calculateMipMapLevel(image->flags, R_KTXWidth(&ktxContext), R_KTXHeight(&ktxContext), image->minmipsize); const uint16_t numberOfMipLevels = R_KTXIsCompressed( &ktxContext ) ? 1 : min(minMipSize, R_KTXGetNumberMips( &ktxContext )); - NriTextureDesc textureDesc = { - .width = R_KTXWidth( &ktxContext ), - .height = R_KTXHeight( &ktxContext ), - .usage = __R_NRITextureUsageBits( image->flags ), - .layerNum = ( image->flags & IT_CUBEMAP ) ? 6 : 1, - .depth = 1, - .format = R_ToNRIFormat( dstFormat ), - .sampleNum = 1, - .type = NriTextureType_TEXTURE_2D, - .mipNum = numberOfMipLevels - }; - - NriResourceGroupDesc resourceGroupDesc = { - .textureNum = 1, - .textures = &image->texture, - .memoryLocation = NriMemoryLocation_DEVICE, - }; - - if( rsh.nri.coreI.CreateTexture( rsh.nri.device, &textureDesc, &image->texture ) != NriResult_SUCCESS ) { - ri.Com_Printf( S_COLOR_YELLOW "Failed to Create Image: %s\n", image->name ); - return false; - } - const uint32_t allocationNum = rsh.nri.helperI.CalculateAllocationNumber( rsh.nri.device, &resourceGroupDesc ); - assert( allocationNum <= Q_ARRAY_COUNT( image->memory ) ); - image->numAllocations = allocationNum; - if( rsh.nri.helperI.AllocateAndBindMemory( rsh.nri.device, &resourceGroupDesc, image->memory ) ) { - ri.Com_Printf( S_COLOR_YELLOW "Failed Allocation: %s\n", image->name ); - return false; - } - - NriTexture2DViewDesc textureViewDesc = { - .texture = image->texture, - .viewType = (image->flags & IT_CUBEMAP) ? NriTexture2DViewType_SHADER_RESOURCE_CUBE: NriTexture2DViewType_SHADER_RESOURCE_2D, - .format = textureDesc.format - }; - NriDescriptor* descriptor = NULL; - NRI_ABORT_ON_FAILURE( rsh.nri.coreI.CreateTexture2DView( &textureViewDesc, &descriptor) ); - image->descriptor = R_CreateDescriptorWrapper( &rsh.nri, descriptor ); - image->samplerDescriptor = R_CreateDescriptorWrapper(&rsh.nri, R_ResolveSamplerDescriptor(image->flags)); - assert(image->samplerDescriptor.descriptor); - rsh.nri.coreI.SetTextureDebugName( image->texture, image->name.buf ); + image->extension = extensionKTX; + image->width = R_KTXWidth(&ktxContext); + image->height = R_KTXHeight(&ktxContext); + GPU_VULKAN_BLOCK( rsh.device.renderer, ( { + uint32_t queueFamilies[RI_QUEUE_LEN] = { 0 }; + VkImageCreateInfo info = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO }; + VkImageCreateFlags flags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT | VK_IMAGE_CREATE_EXTENDED_USAGE_BIT; // typeless + const struct RIFormatProps_s *formatProps = GetRIFormatProps( dstFormat ); + if( formatProps->blockWidth > 1 ) + flags |= VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT; // format can be used to create a view with an uncompressed format (1 texel covers 1 block) + if( image->flags & IT_CUBEMAP ) + flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT; // allow cube maps + // if( desc->type == RI_TEXTURE_3D ) + // flags |= VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT; // allow 3D demotion to a set of layers // TODO: hook up "VK_EXT_image_2d_view_of_3d"? + info.flags = flags; + info.imageType = VK_IMAGE_TYPE_2D; + info.format = RIFormatToVK( dstFormat ); + info.extent.width = image->width; + info.extent.height = image->height; + info.extent.depth = 1; + info.mipLevels = numberOfMipLevels; + info.arrayLayers = ( image->flags & IT_CUBEMAP ) ? 6 : 1; + info.samples = 1; + info.tiling = VK_IMAGE_TILING_OPTIMAL; + + info.pQueueFamilyIndices = queueFamilies; + vk_fillQueueFamilies( &rsh.device, queueFamilies, &info.queueFamilyIndexCount, RI_QUEUE_LEN ); + info.sharingMode = ( info.queueFamilyIndexCount > 0 ) ? VK_SHARING_MODE_CONCURRENT : VK_SHARING_MODE_EXCLUSIVE; // TODO: still no DCC on AMD with concurrent? + info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + VkResult result = vkCreateImage( rsh.device.vk.device, &info, NULL, &image->vk.image ); + if( VK_WrapResult( result ) ) { + goto error; + } + + // allocate vma and bind dedicated VMA + VmaAllocationCreateInfo mem_reqs = { 0 }; + //mem_reqs.flags |= VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT; + mem_reqs.usage = (VmaMemoryUsage)VMA_MEMORY_USAGE_GPU_ONLY; + vmaAllocateMemoryForImage( rsh.device.vk.vmaAllocator, image->vk.image, &mem_reqs, &image->vk.vmaAlloc, NULL ); + vmaBindImageMemory2( rsh.device.vk.vmaAllocator, image->vk.vmaAlloc, 0, image->vk.image, NULL ); + } ) ); + + //NriTextureDesc textureDesc = { + // .width = R_KTXWidth( &ktxContext ), + // .height = R_KTXHeight( &ktxContext ), + // .usage = __R_NRITextureUsageBits( image->flags ), + // .layerNum = ( image->flags & IT_CUBEMAP ) ? 6 : 1, + // .depth = 1, + // .format = R_ToNRIFormat( dstFormat ), + // .sampleNum = 1, + // .type = NriTextureType_TEXTURE_2D, + // .mipNum = numberOfMipLevels + //}; + + //NriResourceGroupDesc resourceGroupDesc = { + // .textureNum = 1, + // .textures = &image->texture, + // .memoryLocation = NriMemoryLocation_DEVICE, + //}; + + //if( rsh.nri.coreI.CreateTexture( rsh.nri.device, &textureDesc, &image->texture ) != NriResult_SUCCESS ) { + // ri.Com_Printf( S_COLOR_YELLOW "Failed to Create Image: %s\n", image->name ); + // return false; + //} + // + //const uint32_t allocationNum = rsh.nri.helperI.CalculateAllocationNumber( rsh.nri.device, &resourceGroupDesc ); + //assert( allocationNum <= Q_ARRAY_COUNT( image->memory ) ); + //image->numAllocations = allocationNum; + //if( rsh.nri.helperI.AllocateAndBindMemory( rsh.nri.device, &resourceGroupDesc, image->memory ) ) { + // ri.Com_Printf( S_COLOR_YELLOW "Failed Allocation: %s\n", image->name ); + // return false; + //} + + //NriTexture2DViewDesc textureViewDesc = { + // .texture = image->texture, + // .viewType = (image->flags & IT_CUBEMAP) ? NriTexture2DViewType_SHADER_RESOURCE_CUBE: NriTexture2DViewType_SHADER_RESOURCE_2D, + // .format = textureDesc.format + //}; + //NriDescriptor* descriptor = NULL; + //NRI_ABORT_ON_FAILURE( rsh.nri.coreI.CreateTexture2DView( &textureViewDesc, &descriptor) ); + //image->descriptor = R_CreateDescriptorWrapper( &rsh.nri, descriptor ); + //image->samplerDescriptor = R_CreateDescriptorWrapper(&rsh.nri, R_ResolveSamplerDescriptor(image->flags)); + //assert(image->samplerDescriptor.descriptor); + //rsh.nri.coreI.SetTextureDebugName( image->texture, image->name.buf ); if( R_KTXIsCompressed( &ktxContext ) ) { struct texture_buf_s uncomp = { 0 }; @@ -860,9 +897,6 @@ static bool __R_LoadKTX( image_t *image, const char *pathname ) } } - image->extension = extensionKTX; - image->width = R_KTXWidth(&ktxContext); - image->height = R_KTXHeight(&ktxContext); R_KTXFreeContext(&ktxContext); R_FreeFile( buffer ); @@ -932,7 +966,7 @@ static enum texture_format_e __R_ResolveDataFormat( int flags, int samples ) static enum texture_format_e __R_GetImageFormat( struct image_s* image ) { assert( ( image->flags & ( IT_FRAMEBUFFER | IT_DEPTHRB | IT_DEPTH ) ) == 0 ); - return R_FORMAT_RGBA8_UNORM; + return RI_FORMAT_RGBA8_UNORM; } static void __R_CopyTextureDataTexture(struct image_s* image, int layer, int mipOffset, int x, int y, int w, int h, enum texture_format_e srcFormat, uint8_t *data ) @@ -967,15 +1001,15 @@ static void __R_CopyTextureDataTexture(struct image_s* image, int layer, int mip memset( &( (uint8_t *)uploadDesc.data )[dstRowStart], 255, uploadDesc.rowPitch ); for( size_t column = 0; column < uploadDesc.width; column++ ) { switch( srcFormat ) { - case R_FORMAT_L8_A8_UNORM: { + case RI_FORMAT_L8_A8_UNORM: { const uint8_t luminance = data[( uploadDesc.width * srcBlockSize * slice ) + ( column * srcBlockSize )]; const uint8_t alpha = data[( uploadDesc.width * srcBlockSize * slice ) + ( column * srcBlockSize ) + 1]; uint8_t color[4] = { luminance, luminance, luminance, alpha }; memcpy( &( (uint8_t *)uploadDesc.data )[dstRowStart + ( destBlockSize * column )], color, min( sizeof( color ), destBlockSize ) ); break; } - case R_FORMAT_A8_UNORM: - case R_FORMAT_R8_UNORM: { + case RI_FORMAT_A8_UNORM: + case RI_FORMAT_R8_UNORM: { const uint8_t c1 = data[( uploadDesc.width * srcBlockSize * slice ) + ( column * srcBlockSize )]; uint8_t color[4]; //= { c1, c1, c1, c1 }; if(image->flags & IT_ALPHAMASK) { @@ -1480,46 +1514,107 @@ image_t *R_FindImage( const char *name, const char *suffix, int flags, int minmi } } assert(uploadCount <= 6); - assert( - (flags & IT_CUBEMAP && uploadCount == 6) || - (!(flags & IT_CUBEMAP) && uploadCount == 1) - ); + assert( ( flags & IT_CUBEMAP && uploadCount == 6 ) || ( !( flags & IT_CUBEMAP ) && uploadCount == 1 ) ); const uint32_t mipSize = __R_calculateMipMapLevel( flags, uploads[0].buffer.width, uploads[0].buffer.height, minmipsize ); - enum texture_format_e destFormat = __R_GetImageFormat(image); - NriTextureDesc textureDesc = { - .width = uploads[0].buffer.width, - .height = uploads[0].buffer.height, - .usage = __R_NRITextureUsageBits( flags ), - .layerNum = uploadCount, - .depth = 1, - .format = R_ToNRIFormat(destFormat), - .sampleNum = 1, - .type = NriTextureType_TEXTURE_2D, - .mipNum = mipSize - }; + const uint32_t destFormat = __R_GetImageFormat( image ); + + GPU_VULKAN_BLOCK( rsh.device.renderer, ( { + uint32_t queueFamilies[RI_QUEUE_LEN] = { 0 }; + VkImageCreateInfo info = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO }; + VkImageCreateFlags flags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT | VK_IMAGE_CREATE_EXTENDED_USAGE_BIT; // typeless + const struct RIFormatProps_s *formatProps = GetRIFormatProps( destFormat ); + if( formatProps->blockWidth > 1 ) + flags |= VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT; // format can be used to create a view with an uncompressed format (1 texel covers 1 block) + if( image->flags & IT_CUBEMAP ) + flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT; // allow cube maps + info.flags = flags; + info.imageType = VK_IMAGE_TYPE_2D; + info.format = RIFormatToVK( destFormat ); + info.extent.width = image->width; + info.extent.height = image->height; + info.extent.depth = 1; + info.mipLevels = mipSize; + info.arrayLayers = ( image->flags & IT_CUBEMAP ) ? 6 : 1; + info.samples = 1; + info.tiling = VK_IMAGE_TILING_OPTIMAL; + + info.pQueueFamilyIndices = queueFamilies; + vk_fillQueueFamilies( &rsh.device, queueFamilies, &info.queueFamilyIndexCount, RI_QUEUE_LEN ); + info.sharingMode = ( info.queueFamilyIndexCount > 0 ) ? VK_SHARING_MODE_CONCURRENT : VK_SHARING_MODE_EXCLUSIVE; // TODO: still no DCC on AMD with concurrent? + info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + VkResult result = vkCreateImage( rsh.device.vk.device, &info, NULL, &image->vk.image ); + if( VK_WrapResult( result ) ) { + ri.Com_Printf( S_COLOR_YELLOW "Failed to Create Image: %s\n", image->name.buf ); + __FreeImage( R_ActiveFrameCmd(), image ); + image = NULL; + goto done; + } + + // allocate vma and bind dedicated VMA + VmaAllocationCreateInfo mem_reqs = { 0 }; + // mem_reqs.flags |= VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT; + mem_reqs.usage = (VmaMemoryUsage)VMA_MEMORY_USAGE_GPU_ONLY; + vmaAllocateMemoryForImage( rsh.device.vk.vmaAllocator, image->vk.image, &mem_reqs, &image->vk.vmaAlloc, NULL ); + vmaBindImageMemory2( rsh.device.vk.vmaAllocator, image->vk.vmaAlloc, 0, image->vk.image, NULL ); + + // create desctipror + VkImageViewUsageCreateInfo usageInfo = {VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO}; + usageInfo.usage |= VK_IMAGE_USAGE_SAMPLED_BIT; + + VkImageSubresourceRange subresource = { + VK_IMAGE_ASPECT_COLOR_BIT, + 0, + info.mipLevels, + 0, + info.arrayLayers, + }; + + VkImageViewCreateInfo createInfo = { VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO }; + createInfo.pNext = &usageInfo; + createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; + createInfo.format = info.format; + createInfo.subresourceRange = subresource; + createInfo.image = image->vk.image; + if( VK_WrapResult( RI_VK_InitImageView(&rsh.device, &createInfo, &image->binding) ) ) { + ri.Com_Printf( S_COLOR_YELLOW "Failed to Create Image: %s\n", image->name.buf ); + __FreeImage( R_ActiveFrameCmd(), image ); + image = NULL; + goto done; + } + } ) ); + + NriTextureDesc textureDesc = { .width = uploads[0].buffer.width, + .height = uploads[0].buffer.height, + .usage = __R_NRITextureUsageBits( flags ), + .layerNum = uploadCount, + .depth = 1, + .format = R_ToNRIFormat( destFormat ), + .sampleNum = 1, + .type = NriTextureType_TEXTURE_2D, + .mipNum = mipSize }; if( rsh.nri.coreI.CreateTexture( rsh.nri.device, &textureDesc, &image->texture ) != NriResult_SUCCESS ) { ri.Com_Printf( S_COLOR_YELLOW "Failed to Create Image: %s\n", image->name.buf ); - __FreeImage( R_ActiveFrameCmd(),image ); - image = NULL; - goto done; - } - rsh.nri.coreI.SetTextureDebugName( image->texture, image->name.buf ); - - NriResourceGroupDesc resourceGroupDesc = { - .textureNum = 1, - .textures = &image->texture, - .memoryLocation = NriMemoryLocation_DEVICE, - }; - const size_t numAllocations = rsh.nri.helperI.CalculateAllocationNumber( rsh.nri.device, &resourceGroupDesc ); - assert( numAllocations <= Q_ARRAY_COUNT( image->memory ) ); - image->numAllocations = numAllocations; - if( rsh.nri.helperI.AllocateAndBindMemory( rsh.nri.device, &resourceGroupDesc, image->memory ) ) { - ri.Com_Printf( S_COLOR_YELLOW "Failed Allocation: %s\n", image->name.buf ); - __FreeImage(R_ActiveFrameCmd(), image ); + __FreeImage( R_ActiveFrameCmd(), image ); image = NULL; goto done; - } + } + rsh.nri.coreI.SetTextureDebugName( image->texture, image->name.buf ); + + NriResourceGroupDesc resourceGroupDesc = { + .textureNum = 1, + .textures = &image->texture, + .memoryLocation = NriMemoryLocation_DEVICE, + }; + const size_t numAllocations = rsh.nri.helperI.CalculateAllocationNumber( rsh.nri.device, &resourceGroupDesc ); + assert( numAllocations <= Q_ARRAY_COUNT( image->memory ) ); + image->numAllocations = numAllocations; + if( rsh.nri.helperI.AllocateAndBindMemory( rsh.nri.device, &resourceGroupDesc, image->memory ) ) { + ri.Com_Printf( S_COLOR_YELLOW "Failed Allocation: %s\n", image->name.buf ); + __FreeImage(R_ActiveFrameCmd(), image ); + image = NULL; + goto done; + } NriTexture2DViewDesc textureViewDesc = { .texture = image->texture, .viewType = (flags & IT_CUBEMAP) ? NriTexture2DViewType_SHADER_RESOURCE_CUBE : NriTexture2DViewType_SHADER_RESOURCE_2D, @@ -1953,9 +2048,7 @@ void R_ShutdownImages( void ) return; for(size_t i = 0; i < IMAGE_SAMPLER_HASH_SIZE; i++) { - if(samplerDescriptors[i].descriptor) { - rsh.nri.coreI.DestroyDescriptor(samplerDescriptors[i].descriptor); - } + FreeRIDescriptor( &rsh.device, &samplerDescriptors[i].descriptor ); } memset(samplerDescriptors, 0, sizeof(samplerDescriptors)); diff --git a/source/ref_nri/r_image.h b/source/ref_nri/r_image.h index b6372fbbb2..ae5849c467 100644 --- a/source/ref_nri/r_image.h +++ b/source/ref_nri/r_image.h @@ -74,6 +74,17 @@ enum typedef struct image_s { + union { + #if(DEVICE_IMPL_VULKAN) + struct { + VkImage image; + struct VmaAllocation_T* vmaAlloc; + } vk; + #endif + }; + struct RIDescriptor_s binding; + struct RIDescriptor_s* samplerBinding; + struct nri_descriptor_s descriptor; struct nri_descriptor_s samplerDescriptor; NriTexture* texture; @@ -120,7 +131,6 @@ void R_ReplaceImage( image_t *image, uint8_t **pic, int width, int height, int f void R_ReplaceSubImage( image_t *image, int layer, int x, int y, uint8_t **pic, int width, int height ); void R_ReplaceImageLayer( image_t *image, int layer, uint8_t **pic ); - -NriDescriptor *R_ResolveSamplerDescriptor( int flags ); +struct RIDescriptor_s* R_ResolveSamplerDescriptor( int flags ); #endif // R_IMAGE_H diff --git a/source/ref_nri/r_local.h b/source/ref_nri/r_local.h index 1481673a92..cc53a39c5e 100644 --- a/source/ref_nri/r_local.h +++ b/source/ref_nri/r_local.h @@ -40,7 +40,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "r_texture_buf.h" #include "../qcommon/mod_win.h" #include "r_graphics.h" - +#include "ri_resource_upload.h" typedef struct { char *name; void **funcPointer; } dllfunc_t; @@ -306,6 +306,8 @@ typedef struct }; } screenshot; + struct RISwapchain_s riSwapchain; + struct shadow_fb_s shadowFBs[NUMBER_FRAMES_FLIGHT][MAX_SHADOWGROUPS]; struct portal_fb_s portalFBs[MAX_PORTAL_TEXTURES]; struct nri_descriptor_s shadowSamplerDescriptor; @@ -314,8 +316,6 @@ typedef struct struct RIRenderer_s renderer; struct RIDevice_s device; - struct RISwapchain_s riSwapchain; - uint64_t frameCount; uint64_t swapchainCount; NriCommandQueue* cmdQueue; @@ -324,6 +324,19 @@ typedef struct struct frame_tex_buffers_s* backBuffers; struct frame_cmd_buffer_s frameCmds[NUMBER_FRAMES_FLIGHT]; + union { +#if ( DEVICE_IMPL_VULKAN ) + struct { + VkImage depthImages[NUMBER_FRAMES_FLIGHT]; + VkImage pogo[NUMBER_FRAMES_FLIGHT * 2]; + + struct RIDescriptor_s depthAttachment[NUMBER_FRAMES_FLIGHT]; + struct RIDescriptor_s colorAttachment[NUMBER_FRAMES_FLIGHT]; + struct RIDescriptor_s pogoAttachment[NUMBER_FRAMES_FLIGHT * 2]; + } vk; +#endif + }; + byte_vec4_t customColors[NUM_CUSTOMCOLORS]; } r_shared_t; diff --git a/source/ref_nri/r_nri.h b/source/ref_nri/r_nri.h index 643d9213f8..044bb7ab46 100644 --- a/source/ref_nri/r_nri.h +++ b/source/ref_nri/r_nri.h @@ -76,6 +76,8 @@ static const char *NriDescriptorTypeToString[NriDescriptorType_MAX_NUM] = { [Nri [NriDescriptorType_STORAGE_STRUCTURED_BUFFER] = "STORAGE_STRUCTURED_BUFFER", [NriDescriptorType_ACCELERATION_STRUCTURE] = "ACCELERATION_STRUCTURE" }; + + // a wrapper to hold onto the hash + cookie struct nri_descriptor_s { NriDescriptor *descriptor; diff --git a/source/ref_nri/r_resource_upload.c b/source/ref_nri/r_resource_upload.c index c7e44c694c..d9de0128ad 100644 --- a/source/ref_nri/r_resource_upload.c +++ b/source/ref_nri/r_resource_upload.c @@ -5,6 +5,7 @@ #include +#include #include "r_local.h" @@ -40,6 +41,7 @@ typedef struct { void *cpuMapping; } resource_stage_response_t; + static NriBufferBarrierDesc* transitionBuffers = NULL; // buffers that need to be transitioned back to frame buffer static NriTextureBarrierDesc* transitionTextures = NULL; // textures that need to be transitioned back to frame buffer @@ -303,7 +305,6 @@ void R_ResourceEndCopyTexture( texture_upload_desc_t *desc ) .access = NriAccessBits_COPY_DESTINATION, .stages = NriStageBits_COPY }; -; transitionBarriers.texture = desc->target; transitionBarriers.after = (NriAccessLayoutStage){ .layout = NriLayout_COPY_DESTINATION, diff --git a/source/ref_nri/r_resource_upload.h b/source/ref_nri/r_resource_upload.h index 92021956d6..baa6f467df 100644 --- a/source/ref_nri/r_resource_upload.h +++ b/source/ref_nri/r_resource_upload.h @@ -58,6 +58,16 @@ typedef struct { NriAccessLayoutStage before; NriAccessLayoutStage after; + union { +#if ( DEVICE_IMPL_VULKAN ) + struct { + VkImage image; + struct VmaAllocation_T* vmaAlloc; + } vk; +#endif + + }; + // https://github.com/microsoft/DirectXTex/wiki/Image uint32_t sliceNum; uint32_t rowPitch; diff --git a/source/ref_nri/ri_format.c b/source/ref_nri/ri_format.c index 26e6dab0d3..e1128fc3de 100644 --- a/source/ref_nri/ri_format.c +++ b/source/ref_nri/ri_format.c @@ -932,4 +932,103 @@ const VkFormat RIFormatToVK(uint32_t format) { } return VK_FORMAT_UNDEFINED; } + + +const enum RI_Format_e VKToRIFormat(VkFormat format) { +switch (format) { + case VK_FORMAT_UNDEFINED: return RI_FORMAT_UNKNOWN; + case VK_FORMAT_R8G8_UNORM: return RI_FORMAT_L8_A8_UNORM; + case VK_FORMAT_R8_UNORM: return RI_FORMAT_A8_UNORM; + case VK_FORMAT_D16_UNORM_S8_UINT: return RI_FORMAT_D16_UNORM_S8_UINT; + case VK_FORMAT_D24_UNORM_S8_UINT: return RI_FORMAT_D24_UNORM_S8_UINT; + case VK_FORMAT_D32_SFLOAT_S8_UINT: return RI_FORMAT_D32_SFLOAT_S8_UINT; + case VK_FORMAT_R8_SNORM: return RI_FORMAT_R8_SNORM; + case VK_FORMAT_R8_UINT: return RI_FORMAT_R8_UINT; + case VK_FORMAT_R8_SINT: return RI_FORMAT_R8_SINT; + case VK_FORMAT_R8G8_SNORM: return RI_FORMAT_RG8_SNORM; + case VK_FORMAT_R8G8_UINT: return RI_FORMAT_RG8_UINT; + case VK_FORMAT_R8G8_SINT: return RI_FORMAT_RG8_SINT; + case VK_FORMAT_B8G8R8A8_UNORM: return RI_FORMAT_BGRA8_UNORM; + case VK_FORMAT_B8G8R8A8_SRGB: return RI_FORMAT_BGRA8_SRGB; + case VK_FORMAT_B8G8R8_UNORM: return RI_FORMAT_BGR8_UNORM; + case VK_FORMAT_R8G8B8_UNORM: return RI_FORMAT_RGB8_UNORM; + case VK_FORMAT_R8G8B8A8_UNORM: return RI_FORMAT_RGBA8_UNORM; + case VK_FORMAT_R8G8B8A8_SNORM: return RI_FORMAT_RGBA8_SNORM; + case VK_FORMAT_R8G8B8A8_UINT: return RI_FORMAT_RGBA8_UINT; + case VK_FORMAT_R8G8B8A8_SINT: return RI_FORMAT_RGBA8_SINT; + case VK_FORMAT_R8G8B8A8_SRGB: return RI_FORMAT_RGBA8_SRGB; + case VK_FORMAT_R16_UNORM: return RI_FORMAT_R16_UNORM; + case VK_FORMAT_R16_SNORM: return RI_FORMAT_R16_SNORM; + case VK_FORMAT_R16_UINT: return RI_FORMAT_R16_UINT; + case VK_FORMAT_R16_SINT: return RI_FORMAT_R16_SINT; + case VK_FORMAT_R16_SFLOAT: return RI_FORMAT_R16_SFLOAT; + case VK_FORMAT_R16G16_UNORM: return RI_FORMAT_RG16_UNORM; + case VK_FORMAT_R16G16_SNORM: return RI_FORMAT_RG16_SNORM; + case VK_FORMAT_R16G16_UINT: return RI_FORMAT_RG16_UINT; + case VK_FORMAT_R16G16_SINT: return RI_FORMAT_RG16_SINT; + case VK_FORMAT_R16G16_SFLOAT: return RI_FORMAT_RG16_SFLOAT; + case VK_FORMAT_R16G16B16A16_UNORM: return RI_FORMAT_RGBA16_UNORM; + case VK_FORMAT_R16G16B16A16_SNORM: return RI_FORMAT_RGBA16_SNORM; + case VK_FORMAT_R16G16B16A16_UINT: return RI_FORMAT_RGBA16_UINT; + case VK_FORMAT_R16G16B16A16_SINT: return RI_FORMAT_RGBA16_SINT; + case VK_FORMAT_R16G16B16A16_SFLOAT: return RI_FORMAT_RGBA16_SFLOAT; + case VK_FORMAT_R32_UINT: return RI_FORMAT_R32_UINT; + case VK_FORMAT_R32_SINT: return RI_FORMAT_R32_SINT; + case VK_FORMAT_R32_SFLOAT: return RI_FORMAT_R32_SFLOAT; + case VK_FORMAT_R32G32_UINT: return RI_FORMAT_RG32_UINT; + case VK_FORMAT_R32G32_SINT: return RI_FORMAT_RG32_SINT; + case VK_FORMAT_R32G32_SFLOAT: return RI_FORMAT_RG32_SFLOAT; + case VK_FORMAT_R32G32B32_UINT: return RI_FORMAT_RGB32_UINT; + case VK_FORMAT_R32G32B32_SINT: return RI_FORMAT_RGB32_SINT; + case VK_FORMAT_R32G32B32_SFLOAT: return RI_FORMAT_RGB32_SFLOAT; + case VK_FORMAT_R32G32B32A32_UINT: return RI_FORMAT_RGBA32_UINT; + case VK_FORMAT_R32G32B32A32_SINT: return RI_FORMAT_RGBA32_SINT; + case VK_FORMAT_R32G32B32A32_SFLOAT: return RI_FORMAT_RGBA32_SFLOAT; + case VK_FORMAT_A2R10G10B10_UNORM_PACK32: return RI_FORMAT_R10_G10_B10_A2_UNORM; + case VK_FORMAT_A2R10G10B10_UINT_PACK32: return RI_FORMAT_R10_G10_B10_A2_UINT; + case VK_FORMAT_B10G11R11_UFLOAT_PACK32: return RI_FORMAT_R11_G11_B10_UFLOAT; + case VK_FORMAT_E5B9G9R9_UFLOAT_PACK32: return RI_FORMAT_R9_G9_B9_E5_UNORM; + case VK_FORMAT_R5G6B5_UNORM_PACK16: return RI_FORMAT_R5_G6_B5_UNORM; + case VK_FORMAT_A1R5G5B5_UNORM_PACK16: return RI_FORMAT_R5_G5_B5_A1_UNORM; + case VK_FORMAT_R4G4B4A4_UNORM_PACK16: return RI_FORMAT_R4_G4_B4_A4_UNORM; + case VK_FORMAT_BC1_RGBA_UNORM_BLOCK: return RI_FORMAT_BC1_RGBA_UNORM; + case VK_FORMAT_BC1_RGBA_SRGB_BLOCK: return RI_FORMAT_BC1_RGBA_SRGB; + case VK_FORMAT_BC2_UNORM_BLOCK: return RI_FORMAT_BC2_RGBA_UNORM; + case VK_FORMAT_BC2_SRGB_BLOCK: return RI_FORMAT_BC2_RGBA_SRGB; + case VK_FORMAT_BC3_UNORM_BLOCK: return RI_FORMAT_BC3_RGBA_UNORM; + case VK_FORMAT_BC3_SRGB_BLOCK: return RI_FORMAT_BC3_RGBA_SRGB; + case VK_FORMAT_BC4_UNORM_BLOCK: return RI_FORMAT_BC4_R_UNORM; + case VK_FORMAT_BC4_SNORM_BLOCK: return RI_FORMAT_BC4_R_SNORM; + case VK_FORMAT_BC5_UNORM_BLOCK: return RI_FORMAT_BC5_RG_UNORM; + case VK_FORMAT_BC5_SNORM_BLOCK: return RI_FORMAT_BC5_RG_SNORM; + case VK_FORMAT_BC6H_UFLOAT_BLOCK: return RI_FORMAT_BC6H_RGB_UFLOAT; + case VK_FORMAT_BC6H_SFLOAT_BLOCK: return RI_FORMAT_BC6H_RGB_SFLOAT; + case VK_FORMAT_BC7_UNORM_BLOCK: return RI_FORMAT_BC7_RGBA_UNORM; + case VK_FORMAT_BC7_SRGB_BLOCK: return RI_FORMAT_BC7_RGBA_SRGB; + case VK_FORMAT_D16_UNORM: return RI_FORMAT_D16_UNORM; + case VK_FORMAT_D32_SFLOAT: return RI_FORMAT_D32_SFLOAT; + // case VK_FORMAT_D32_SFLOAT_S8_UINT: return RI_FORMAT_D32_SFLOAT_S8_UINT_X24; + case VK_FORMAT_X8_D24_UNORM_PACK32: return RI_FORMAT_R24_UNORM_X8; + // case VK_FORMAT_X8_D24_UNORM_PACK32: return RI_FORMAT_X24_R8_UINT; + // case VK_FORMAT_D32_SFLOAT_S8_UINT: return RI_FORMAT_X32_R8_UINT_X24; + // case VK_FORMAT_D32_SFLOAT_S8_UINT: return RI_FORMAT_R32_SFLOAT_X8_X24; + case VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK: return RI_FORMAT_ETC1_R8G8B8_OES; + // case VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK: return RI_FORMAT_ETC2_R8G8B8_UNORM; + case VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK: return RI_FORMAT_ETC2_R8G8B8_SRGB; + case VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK: return RI_FORMAT_ETC2_R8G8B8A1_UNORM; + case VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK: return RI_FORMAT_ETC2_R8G8B8A1_SRGB; + case VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK: return RI_FORMAT_ETC2_R8G8B8A8_UNORM; + case VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK: return RI_FORMAT_ETC2_R8G8B8A8_SRGB; + case VK_FORMAT_EAC_R11_UNORM_BLOCK: return RI_FORMAT_ETC2_EAC_R11_UNORM; + case VK_FORMAT_EAC_R11_SNORM_BLOCK: return RI_FORMAT_ETC2_EAC_R11_SNORM; + case VK_FORMAT_EAC_R11G11_UNORM_BLOCK: return RI_FORMAT_ETC2_EAC_R11G11_UNORM; + case VK_FORMAT_EAC_R11G11_SNORM_BLOCK: return RI_FORMAT_ETC2_EAC_R11G11_SNORM; + default: { + const struct RIFormatProps_s* fmt = GetRIFormatProps(format); + Com_Printf("Unhandled RI_Format to VK %d\n", fmt->name); + break; + } + } + return RI_FORMAT_UNKNOWN; +} #endif diff --git a/source/ref_nri/ri_format.h b/source/ref_nri/ri_format.h index 7638bb3d67..9b284c1216 100644 --- a/source/ref_nri/ri_format.h +++ b/source/ref_nri/ri_format.h @@ -1,3 +1,6 @@ +#ifndef RI_FORMAT_H +#define RI_FORMAT_H + #include #include "ri_types.h" @@ -147,4 +150,7 @@ const struct RIFormatProps_s* GetRIFormatProps(uint32_t format); #if DEVICE_IMPL_VULKAN const VkFormat RIFormatToVK(uint32_t format); +const enum RI_Format_e VKToRIFormat(VkFormat); +#endif + #endif diff --git a/source/ref_nri/ri_renderer.c b/source/ref_nri/ri_renderer.c index 7f6c408332..19dbfee64c 100644 --- a/source/ref_nri/ri_renderer.c +++ b/source/ref_nri/ri_renderer.c @@ -78,6 +78,21 @@ const static char *DefaultDeviceExtension[] = { VK_EXT_ASTC_DECODE_MODE_EXTENSION_NAME, }; +void vk_fillQueueFamilies( struct RIDevice_s *dev, uint32_t *queueFamilies, uint32_t *queueFamiliesIdx, size_t reservedLen ) +{ + uint32_t uniqueQueue = 0; + for( size_t i = 0; i < RI_QUEUE_LEN; i++ ) { + if( dev->queues[i].vk.queue ) { + const uint32_t queueBit = ( 1 << dev->queues[i].vk.queueFamilyIdx ); + if( ( uniqueQueue & queueBit ) > 0 ) { + assert( ( *queueFamiliesIdx ) < reservedLen ); + queueFamilies[( *queueFamiliesIdx )++] = dev->queues[i].vk.queueFamilyIdx; + } + uniqueQueue |= queueBit; + } + } +} + VkBool32 VKAPI_PTR __VK_DebugUtilsMessenger( VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageType, const VkDebugUtilsMessengerCallbackDataEXT *callbackData, @@ -437,7 +452,8 @@ int InitRIDevice(struct RIRenderer_s* renderer, struct RIDeviceDesc_s* init, str const uint32_t requiredFlags = configureQueue[initIdx].requiredBits; for( size_t familyIdx = 0; familyIdx < familyNum; familyIdx++ ) { uint32_t avaliableQueues = 0; - for( size_t createQueueIdx = 0; createQueueIdx < Q_ARRAY_COUNT( queueCreateInfoPool ); createQueueIdx++ ) { + size_t createQueueIdx = 0; + for( ; createQueueIdx < Q_ARRAY_COUNT( queueCreateInfoPool ); createQueueIdx++ ) { const bool foundQueueFamily = queueCreateInfoPool[createQueueIdx].queueFamilyIndex == familyIdx; if( foundQueueFamily || queueCreateInfoPool[createQueueIdx].queueCount == 0 ) { selectedQueue = &queueCreateInfoPool[createQueueIdx]; diff --git a/source/ref_nri/ri_renderer.h b/source/ref_nri/ri_renderer.h index 0edd0865d4..ecc878e34b 100644 --- a/source/ref_nri/ri_renderer.h +++ b/source/ref_nri/ri_renderer.h @@ -29,5 +29,11 @@ int EnumerateRIAdapters(struct RIRenderer_s* renderer,struct RIPhysicalAdapter_s int InitRIDevice(struct RIRenderer_s* renderer, struct RIDeviceDesc_s* init, struct RIDevice_s* device); int FreeRIDevice(struct RIDevice_s* dev); +#if DEVICE_IMPL_VULKAN + void vk_fillQueueFamilies(struct RIDevice_s* dev, uint32_t* queueFamilies, uint32_t* queueFamiliesIdx, size_t reservedLen); +#endif + + + #endif diff --git a/source/ref_nri/ri_resource.c b/source/ref_nri/ri_resource.c index ced422f573..651fd1a9a2 100644 --- a/source/ref_nri/ri_resource.c +++ b/source/ref_nri/ri_resource.c @@ -2,159 +2,208 @@ #include "ri_conversion.h" #include "ri_format.h" -#include +#include "ri_types.h" -#if DEVICE_IMPL_VULKAN +static uint32_t cookie = 0; - static inline void __vk_fillQueueFamilies(struct RIDevice_s* dev, uint32_t* queueFamilies, uint32_t* queueFamiliesIdx, size_t reservedLen) { - uint32_t uniqueQueue = 0; - for( size_t i = 0; i < RI_QUEUE_LEN; i++ ) { - if( dev->queues[i].vk.queue ) { - const uint32_t queueBit = ( 1 << dev->queues[i].vk.queueFamilyIdx ); - if( ( uniqueQueue & queueBit ) > 0 ) { - assert(*queueFamiliesIdx < reservedLen); - queueFamilies[(*queueFamiliesIdx)++] = dev->queues[i].vk.queueFamilyIdx; - - } - uniqueQueue |= queueBit; - } - } - } +#if DEVICE_IMPL_VULKAN +VkResult RI_VK_InitImageView(struct RIDevice_s* dev,VkImageViewCreateInfo* info, struct RIDescriptor_s* desc) { + assert(dev->renderer->api == RI_DEVICE_API_VK); + desc->cookie = cookie++; + desc->vk.type = RI_DESCRIPTOR_BUFFER_VIEW; + return vkCreateImageView( dev->vk.device, info, NULL, &desc->vk.image.view); +} +VkResult RI_VK_InitSampler(struct RIDevice_s* dev, VkSamplerCreateInfo* info, struct RIDescriptor_s* desc) { + assert(dev->renderer->api == RI_DEVICE_API_VK); + desc->cookie = cookie++; + desc->vk.type = RI_DESCRIPTOR_SAMPLER; + return vkCreateSampler( dev->vk.device, info, NULL, &desc->vk.sampler.sampler); +} #endif -int InitRITexture( struct RIDevice_s *dev, const struct RITextureDesc_s *desc, struct RITexture_s *tex, struct RIMemory_s* mem) +bool IsEmptyDescriptor( struct RIDevice_s *dev, struct RIDescriptor_s *desc ) { - GPU_VULKAN_BLOCK( dev->renderer, ( { - tex->height = desc->height; - tex->width = desc->width; - tex->type = desc->type; - tex->sampleNum = desc->sampleNum; - tex->mipNum = desc->mipNum; - tex->depth = desc->depth; - uint32_t queueFamilies[RI_QUEUE_LEN] = { 0 }; - VkImageCreateInfo info = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO }; - VkImageCreateFlags flags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT | VK_IMAGE_CREATE_EXTENDED_USAGE_BIT; // typeless - const struct RIFormatProps_s *formatProps = GetRIFormatProps( desc->format ); - if( formatProps->blockWidth > 1 ) - flags |= VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT; // format can be used to create a view with an uncompressed format (1 texel covers 1 block) - if( desc->layerNum >= 6 && desc->width == desc->height ) - flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT; // allow cube maps - if( desc->type == RI_TEXTURE_3D ) - flags |= VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT; // allow 3D demotion to a set of layers // TODO: hook up "VK_EXT_image_2d_view_of_3d"? - // if (m_Desc.sampleLocationsTier && formatProps.isDepth) - // flags |= VK_IMAGE_CREATE_SAMPLE_LOCATIONS_COMPATIBLE_DEPTH_BIT_EXT; - - info.flags = flags; - info.imageType = ri_vk_RITextureTypeToVKImageType( desc->type ); - info.format = RIFormatToVK( desc->format ); - info.extent.width = desc->width; - info.extent.height = Q_MAX( desc->height, 1 ); - info.extent.depth = Q_MAX( desc->depth, 1 ); - info.mipLevels = Q_MAX( desc->mipNum, 1 ); - info.arrayLayers = Q_MAX( desc->layerNum, 1 ); - info.samples = Q_MAX( desc->sampleNum, 1 ); - info.tiling = VK_IMAGE_TILING_OPTIMAL; - - info.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; - if( desc->usageBits & RI_USAGE_SHADER_RESOURCE ) - info.usage |= VK_IMAGE_USAGE_SAMPLED_BIT; - if( desc->usageBits & RI_USAGE_SHADER_RESOURCE_STORAGE ) - info.usage |= VK_IMAGE_USAGE_STORAGE_BIT; - if( desc->usageBits & RI_USAGE_COLOR_ATTACHMENT ) - info.usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; - if( desc->usageBits & RI_USAGE_DEPTH_STENCIL_ATTACHMENT ) - info.usage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; - if( desc->usageBits & RI_USAGE_SHADING_RATE ) - info.usage |= VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR; - - info.pQueueFamilyIndices = queueFamilies; - __vk_fillQueueFamilies( dev, queueFamilies, &info.queueFamilyIndexCount, RI_QUEUE_LEN ); - - info.sharingMode = ( info.queueFamilyIndexCount > 0 ) ? VK_SHARING_MODE_CONCURRENT : VK_SHARING_MODE_EXCLUSIVE; // TODO: still no DCC on AMD with concurrent? - info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - VkResult result = vkCreateImage( dev->vk.device, &info, NULL, &tex->vk.image ); - if( VK_WrapResult( result ) ) { - return RI_FAIL; - } - - // allocate vma and bind dedicated VMA - VmaAllocationCreateInfo mem_reqs = { 0 }; - mem_reqs.flags |= VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT; - mem_reqs.usage = (VmaMemoryUsage)VMA_MEMORY_USAGE_GPU_ONLY; - vmaAllocateMemoryForImage( dev->vk.vmaAllocator, tex->vk.image, &mem_reqs, &mem->vk.vmaAlloc, NULL ); - vmaBindImageMemory2(dev->vk.vmaAllocator, mem->vk.vmaAlloc, 0, tex->vk.image, NULL); - - return RI_SUCCESS; - } ) ); - return RI_INCOMPLETE_DEVICE; -} -void FreeRITexture( struct RIDevice_s *dev, struct RITexture_s *tex ) {} - -void FreeRIMemory(struct RIDevice_s* dev, struct RIMemory_s* mem) { - GPU_VULKAN_BLOCK( dev->renderer, ( { - if(mem->vk.vmaAlloc) { - vmaFreeMemory(dev->vk.vmaAllocator, mem->vk.vmaAlloc); - } - } ) ); + GPU_VULKAN_BLOCK( dev->renderer, ( { return desc->vk.type == RI_DESCRIPTOR_NONE; } ) ); + return true; } -int initRIBuffer( struct RIDevice_s *dev, const struct RIBufferDesc_s *desc, struct RIBuffer_s *buf, struct RIMemory_s* mem) +void FreeRIDescriptor( struct RIDevice_s *dev, struct RIDescriptor_s *desc ) { GPU_VULKAN_BLOCK( dev->renderer, ( { - uint32_t queueFamilies[RI_QUEUE_LEN] = { 0 }; - VkBufferCreateInfo info = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO }; - info.size = desc->size; - info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT; - if( dev->physicalAdapter.vk.isBufferDeviceAddressSupported ) - info.usage |= VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT; - if( desc->usageBits & RI_BUFFER_USAGE_VERTEX_BUFFER ) - info.usage |= VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; - - if( desc->usageBits & RI_BUFFER_USAGE_INDEX_BUFFER ) - info.usage |= VK_BUFFER_USAGE_INDEX_BUFFER_BIT; - - if( desc->usageBits & RI_BUFFER_USAGE_CONSTANT_BUFFER ) - info.usage |= VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT; - - if( desc->usageBits & RI_BUFFER_USAGE_ARGUMENT_BUFFER ) - info.usage |= VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT; - - if( desc->usageBits & RI_BUFFER_USAGE_SCRATCH ) - info.usage |= VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; - - if( desc->usageBits & RI_BUFFER_USAGE_BINDING_TABLE ) - info.usage |= VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR; - - if( desc->usageBits & RI_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE ) - info.usage |= VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR; - - if( desc->usageBits & RI_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPT ) - info.usage |= VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR; - - if( desc->usageBits & RI_BUFFER_USAGE_SHADER_RESOURCE ) - info.usage |= desc->structureStride > 0 ? VK_BUFFER_USAGE_STORAGE_BUFFER_BIT : VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT; - - if( desc->usageBits & RI_BUFFER_USAGE_SHADER_RESOURCE_STORAGE ) - info.usage |= desc->structureStride > 0 ? VK_BUFFER_USAGE_STORAGE_BUFFER_BIT : VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT; - - info.pQueueFamilyIndices = queueFamilies; - __vk_fillQueueFamilies( dev, queueFamilies, &info.queueFamilyIndexCount, RI_QUEUE_LEN ); - info.sharingMode = ( info.queueFamilyIndexCount > 0 ) ? VK_SHARING_MODE_CONCURRENT : VK_SHARING_MODE_EXCLUSIVE; // TODO: still no DCC on AMD with concurrent? - - VkResult result = vkCreateBuffer( dev->vk.device, &info, NULL, &buf->vk.buffer ); - if( VK_WrapResult( result ) ) { - return RI_FAIL; + switch( desc->vk.type ) { + case RI_DESCRIPTOR_BUFFER_VIEW: + break; + case RI_DESCRIPTOR_IMAGE_VIEW: + vkDestroyImageView( dev->vk.device, desc->vk.image.view, NULL ); + break; + case RI_DESCRIPTOR_SAMPLER: + vkDestroySampler( dev->vk.device, desc->vk.sampler.sampler, NULL ); + break; + case RI_DESCRIPTOR_ACCELERATION_STRUCTURE: + break; + default: + break; } - - VmaAllocationCreateInfo mem_reqs = { 0 }; - mem_reqs.flags |= VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT; - mem_reqs.usage = (VmaMemoryUsage)VMA_MEMORY_USAGE_GPU_ONLY; - vmaAllocateMemoryForBuffer(dev->vk.vmaAllocator, buf->vk.buffer, &mem_reqs, &mem->vk.vmaAlloc, NULL); - vmaBindBufferMemory2(dev->vk.vmaAllocator, mem->vk.vmaAlloc, 0, buf->vk.buffer, NULL); - - return RI_SUCCESS; } ) ); - return RI_INCOMPLETE_DEVICE; + memset( desc, 0, sizeof( struct RIDescriptor_s ) ); } +//#if DEVICE_IMPL_VULKAN +// +// static inline void __vk_fillQueueFamilies(struct RIDevice_s* dev, uint32_t* queueFamilies, uint32_t* queueFamiliesIdx, size_t reservedLen) { +// uint32_t uniqueQueue = 0; +// for( size_t i = 0; i < RI_QUEUE_LEN; i++ ) { +// if( dev->queues[i].vk.queue ) { +// const uint32_t queueBit = ( 1 << dev->queues[i].vk.queueFamilyIdx ); +// if( ( uniqueQueue & queueBit ) > 0 ) { +// assert(*queueFamiliesIdx < reservedLen); +// queueFamilies[(*queueFamiliesIdx)++] = dev->queues[i].vk.queueFamilyIdx; +// +// } +// uniqueQueue |= queueBit; +// } +// } +// } +// +//#endif +// +//int InitRITexture( struct RIDevice_s *dev, const struct RITextureDesc_s *desc, struct RITextureHandle_s *tex, struct RIMemory_s* mem) +//{ +// GPU_VULKAN_BLOCK( dev->renderer, ( { +// tex->height = desc->height; +// tex->width = desc->width; +// tex->type = desc->type; +// tex->sampleNum = desc->sampleNum; +// tex->mipNum = desc->mipNum; +// tex->depth = desc->depth; +// uint32_t queueFamilies[RI_QUEUE_LEN] = { 0 }; +// VkImageCreateInfo info = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO }; +// VkImageCreateFlags flags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT | VK_IMAGE_CREATE_EXTENDED_USAGE_BIT; // typeless +// const struct RIFormatProps_s *formatProps = GetRIFormatProps( desc->format ); +// if( formatProps->blockWidth > 1 ) +// flags |= VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT; // format can be used to create a view with an uncompressed format (1 texel covers 1 block) +// if( desc->layerNum >= 6 && desc->width == desc->height ) +// flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT; // allow cube maps +// if( desc->type == RI_TEXTURE_3D ) +// flags |= VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT; // allow 3D demotion to a set of layers // TODO: hook up "VK_EXT_image_2d_view_of_3d"? +// // if (m_Desc.sampleLocationsTier && formatProps.isDepth) +// // flags |= VK_IMAGE_CREATE_SAMPLE_LOCATIONS_COMPATIBLE_DEPTH_BIT_EXT; +// +// info.flags = flags; +// info.imageType = ri_vk_RITextureTypeToVKImageType( desc->type ); +// info.format = RIFormatToVK( desc->format ); +// info.extent.width = desc->width; +// info.extent.height = Q_MAX( desc->height, 1 ); +// info.extent.depth = Q_MAX( desc->depth, 1 ); +// info.mipLevels = Q_MAX( desc->mipNum, 1 ); +// info.arrayLayers = Q_MAX( desc->layerNum, 1 ); +// info.samples = Q_MAX( desc->sampleNum, 1 ); +// info.tiling = VK_IMAGE_TILING_OPTIMAL; +// +// info.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; +// if( desc->usageBits & RI_USAGE_SHADER_RESOURCE ) +// info.usage |= VK_IMAGE_USAGE_SAMPLED_BIT; +// if( desc->usageBits & RI_USAGE_SHADER_RESOURCE_STORAGE ) +// info.usage |= VK_IMAGE_USAGE_STORAGE_BIT; +// if( desc->usageBits & RI_USAGE_COLOR_ATTACHMENT ) +// info.usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; +// if( desc->usageBits & RI_USAGE_DEPTH_STENCIL_ATTACHMENT ) +// info.usage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; +// if( desc->usageBits & RI_USAGE_SHADING_RATE ) +// info.usage |= VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR; +// +// info.pQueueFamilyIndices = queueFamilies; +// __vk_fillQueueFamilies( dev, queueFamilies, &info.queueFamilyIndexCount, RI_QUEUE_LEN ); +// +// info.sharingMode = ( info.queueFamilyIndexCount > 0 ) ? VK_SHARING_MODE_CONCURRENT : VK_SHARING_MODE_EXCLUSIVE; // TODO: still no DCC on AMD with concurrent? +// info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; +// VkResult result = vkCreateImage( dev->vk.device, &info, NULL, &tex->vk.image ); +// if( VK_WrapResult( result ) ) { +// return RI_FAIL; +// } +// +// // allocate vma and bind dedicated VMA +// VmaAllocationCreateInfo mem_reqs = { 0 }; +// mem_reqs.flags |= VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT; +// mem_reqs.usage = (VmaMemoryUsage)VMA_MEMORY_USAGE_GPU_ONLY; +// vmaAllocateMemoryForImage( dev->vk.vmaAllocator, tex->vk.image, &mem_reqs, &mem->vk.vmaAlloc, NULL ); +// vmaBindImageMemory2(dev->vk.vmaAllocator, mem->vk.vmaAlloc, 0, tex->vk.image, NULL); +// +// return RI_SUCCESS; +// } ) ); +// return RI_INCOMPLETE_DEVICE; +//} +//void FreeRITexture( struct RIDevice_s *dev, struct RITextureHandle_s *tex ) {} +// +//void FreeRIMemory(struct RIDevice_s* dev, struct RIMemory_s* mem) { +// GPU_VULKAN_BLOCK( dev->renderer, ( { +// if(mem->vk.vmaAlloc) { +// vmaFreeMemory(dev->vk.vmaAllocator, mem->vk.vmaAlloc); +// } +// } ) ); +//} +// +//int InitRIBuffer( struct RIDevice_s *dev, const struct RIBufferDesc_s *desc, struct RIBuffer_s *buf, struct RIMemory_s *mem ) +//{ +// GPU_VULKAN_BLOCK( dev->renderer, ( { +// uint32_t queueFamilies[RI_QUEUE_LEN] = { 0 }; +// VkBufferCreateInfo info = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO }; +// info.size = desc->size; +// info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT; +// if( dev->physicalAdapter.vk.isBufferDeviceAddressSupported ) +// info.usage |= VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT; +// if( desc->usageBits & RI_BUFFER_USAGE_VERTEX_BUFFER ) +// info.usage |= VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; +// +// if( desc->usageBits & RI_BUFFER_USAGE_INDEX_BUFFER ) +// info.usage |= VK_BUFFER_USAGE_INDEX_BUFFER_BIT; +// +// if( desc->usageBits & RI_BUFFER_USAGE_CONSTANT_BUFFER ) +// info.usage |= VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT; +// +// if( desc->usageBits & RI_BUFFER_USAGE_ARGUMENT_BUFFER ) +// info.usage |= VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT; +// +// if( desc->usageBits & RI_BUFFER_USAGE_SCRATCH ) +// info.usage |= VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; +// +// if( desc->usageBits & RI_BUFFER_USAGE_BINDING_TABLE ) +// info.usage |= VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR; +// +// if( desc->usageBits & RI_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE ) +// info.usage |= VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR; +// +// if( desc->usageBits & RI_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPT ) +// info.usage |= VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR; +// +// if( desc->usageBits & RI_BUFFER_USAGE_SHADER_RESOURCE ) +// info.usage |= desc->structureStride > 0 ? VK_BUFFER_USAGE_STORAGE_BUFFER_BIT : VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT; +// +// if( desc->usageBits & RI_BUFFER_USAGE_SHADER_RESOURCE_STORAGE ) +// info.usage |= desc->structureStride > 0 ? VK_BUFFER_USAGE_STORAGE_BUFFER_BIT : VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT; +// +// info.pQueueFamilyIndices = queueFamilies; +// __vk_fillQueueFamilies( dev, queueFamilies, &info.queueFamilyIndexCount, RI_QUEUE_LEN ); +// info.sharingMode = ( info.queueFamilyIndexCount > 0 ) ? VK_SHARING_MODE_CONCURRENT : VK_SHARING_MODE_EXCLUSIVE; // TODO: still no DCC on AMD with concurrent? +// +// VkResult result = vkCreateBuffer( dev->vk.device, &info, NULL, &buf->vk.buffer ); +// if( VK_WrapResult( result ) ) { +// return RI_FAIL; +// } +// +// VmaAllocationCreateInfo mem_reqs = { 0 }; +// mem_reqs.flags |= VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT; +// mem_reqs.usage = (VmaMemoryUsage)VMA_MEMORY_USAGE_GPU_ONLY; +// vmaAllocateMemoryForBuffer( dev->vk.vmaAllocator, buf->vk.buffer, &mem_reqs, &mem->vk.vmaAlloc, NULL ); +// vmaBindBufferMemory2( dev->vk.vmaAllocator, mem->vk.vmaAlloc, 0, buf->vk.buffer, NULL ); +// +// return RI_SUCCESS; +// } ) ); +// return RI_INCOMPLETE_DEVICE; +//} +// +//void FreeRIBuffer(struct RIDevice_s* dev, struct RIBuffer_s *buf) { +// +//} + diff --git a/source/ref_nri/ri_resource.h b/source/ref_nri/ri_resource.h index 2da2e27431..5d29b4d280 100644 --- a/source/ref_nri/ri_resource.h +++ b/source/ref_nri/ri_resource.h @@ -3,27 +3,12 @@ #include "ri_types.h" +#if DEVICE_IMPL_VULKAN +VkResult RI_VK_InitImageView(struct RIDevice_s* dev,VkImageViewCreateInfo* info, struct RIDescriptor_s* desc); +VkResult RI_VK_InitSampler(struct RIDevice_s* dev, VkSamplerCreateInfo* info, struct RIDescriptor_s* desc); +#endif -struct RITextureDesc_s { - uint16_t type; // RITextureType_e - uint16_t sampleNum; // RISampleCount_e - uint32_t format; // RI_Format_e - uint16_t width, height, depth; - uint8_t layerNum; - uint8_t mipNum; - uint32_t usageBits; // RITextureUsageBits_e -}; - -int InitRITexture( struct RIDevice_s *dev, const struct RITextureDesc_s *desc, struct RITexture_s *tex, struct RIMemory_s* mem); -void FreeRITexture( struct RIDevice_s *dev, struct RITexture_s *tex ); - -struct RIBufferDesc_s { - uint64_t size; - uint32_t usageBits; // RIBufferUsage_e - uint64_t structureStride; // optional field if the data has a stride -}; - -int initRIBuffer(struct RIDevice_s* dev, const struct RIBufferDesc_s* desc, struct RIBuffer_s *buf, struct RIMemory_s* mem); +bool IsEmptyDescriptor(struct RIDevice_s* dev,struct RIDescriptor_s* desc); +void FreeRIDescriptor(struct RIDevice_s* dev,struct RIDescriptor_s* desc); -void FreeRIMemory(struct RIDevice_s* dev, struct RIMemory_s* mem); #endif diff --git a/source/ref_nri/ri_resource_upload.c b/source/ref_nri/ri_resource_upload.c new file mode 100644 index 0000000000..9ae4b13adf --- /dev/null +++ b/source/ref_nri/ri_resource_upload.c @@ -0,0 +1,202 @@ +#include "ri_resource_upload.h" +#include "ri_types.h" +#include "qtypes.h" + +#include +#include "ri_format.h" + + +static void __EndActiveCommandSet( struct RIDevice_s *device, struct RIResourceUploader_s *res ) { + GPU_VULKAN_BLOCK( device->renderer, ( { + vkEndCommandBuffer(res->vk.cmdSets[res->activeSet].cmdBuffer); + + + vkQueueSubmit(res->copyQueue->vk.queue, 1, NULL, NULL); + } ) ); + +} + +static void __BeginNewCommandSet( struct RIDevice_s *device, struct RIResourceUploader_s *res ) +{ + res->remaningSpace += res->reservedSpacePerSet[res->activeSet]; + res->reservedSpacePerSet[res->activeSet] = 0; + GPU_VULKAN_BLOCK( device->renderer, ( { + VkCommandBufferBeginInfo info = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO }; + info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; + vkBeginCommandBuffer( res->vk.cmdSets[res->activeSet].cmdBuffer, &info ); + } ) ); +} + +void RI_InitResourceUploader( struct RIDevice_s *device, struct RIResourceUploader_s *resource ) +{ + GPU_VULKAN_BLOCK( device->renderer, ( { + resource->copyQueue = &device->queues[RI_QUEUE_COPY]; + for( size_t i = 0; i < RI_RESOURCE_NUM_COMMAND_SETS; i++ ) { + VkCommandPoolCreateInfo cmdPoolCreateInfo = { VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO }; + cmdPoolCreateInfo.queueFamilyIndex = resource->copyQueue->vk.queueFamilyIdx; + cmdPoolCreateInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; + VK_WrapResult( vkCreateCommandPool( device->vk.device, &cmdPoolCreateInfo, NULL, &resource->vk.cmdSets[i].cmdPool ) ); + + VkCommandBufferAllocateInfo cmdAllocInfo = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO }; + cmdAllocInfo.commandPool = resource->vk.cmdSets[i].cmdPool; + cmdAllocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; + cmdAllocInfo.commandBufferCount = 1; + vkAllocateCommandBuffers( device->vk.device, &cmdAllocInfo, &resource->vk.cmdSets[i].cmdBuffer ); + } + { + VkBufferCreateInfo stageBufferCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO }; + stageBufferCreateInfo.pNext = NULL; + stageBufferCreateInfo.flags = 0; + stageBufferCreateInfo.size = RI_RESOURCE_STAGE_SIZE; + stageBufferCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; + stageBufferCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + stageBufferCreateInfo.queueFamilyIndexCount = 0; + stageBufferCreateInfo.pQueueFamilyIndices = NULL; + VK_WrapResult( vkCreateBuffer( device->vk.device, &stageBufferCreateInfo, NULL, &resource->vk.stageBuffer ) ); + + VmaAllocationInfo allocationInfo = {}; + VmaAllocationCreateInfo allocInfo = {}; + allocInfo.flags |= VMA_ALLOCATION_CREATE_MAPPED_BIT; + vmaAllocateMemoryForBuffer( device->vk.vmaAllocator, resource->vk.stageBuffer, &allocInfo, &resource->vk.stageAlloc, &allocationInfo); + vmaBindBufferMemory2( device->vk.vmaAllocator, resource->vk.stageAlloc, 0, resource->vk.stageBuffer, NULL ); + resource->vk.pMappedData = allocationInfo.pMappedData; + } + } ) ); + __BeginNewCommandSet( device, resource ); +} + +static bool __R_AllocFromStageBuffer( struct RIDevice_s *dev, struct RIResourceUploader_s *res, size_t reqSize, struct RIResourceReq *req ) +{ + size_t allocSize = Q_ALIGN_TO( reqSize, 4 ); // we round up to multiples of uint32_t + if( allocSize > res->remaningSpace ) { + // we are out of avaliable space from staging + return false; + } + + // we are past the end of the buffer + if( res->tailOffset + allocSize > RI_RESOURCE_STAGE_SIZE ) { + const size_t remainingSpace = ( RI_RESOURCE_STAGE_SIZE - res->tailOffset ); // remaining space at the end of the buffer this unusable + if( allocSize > res->remaningSpace - remainingSpace ) { + return false; + } + + res->remaningSpace -= remainingSpace; + res->reservedSpacePerSet[res->activeSet] += remainingSpace; // give the remaning space to the requesting set + res->tailOffset = 0; + } + + GPU_VULKAN_BLOCK( dev->renderer, ( { + req->vk.alloc = res->vk.stageAlloc; + req->cpuMapping = res->vk.pMappedData; + req->byteOffset = res->tailOffset; + req->vk.buffer = res->vk.stageBuffer; + } ) ); + + res->reservedSpacePerSet[res->activeSet] += allocSize; + + res->tailOffset += allocSize; + res->remaningSpace -= allocSize; + return true; +} + +static bool __ResolveStageBuffer( struct RIDevice_s *dev, struct RIResourceUploader_s *res, size_t reqSize, struct RIResourceReq *req ) +{ + if( __R_AllocFromStageBuffer( dev, res, reqSize, req ) ) { + return true; + } + GPU_VULKAN_BLOCK( dev->renderer, ( { + struct RI_VK_TempBuffers tempBuffer; + VkBufferCreateInfo stageBufferCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO }; + stageBufferCreateInfo.pNext = NULL; + stageBufferCreateInfo.flags = 0; + stageBufferCreateInfo.size = reqSize; + stageBufferCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; + stageBufferCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + stageBufferCreateInfo.queueFamilyIndexCount = 0; + stageBufferCreateInfo.pQueueFamilyIndices = NULL; + VK_WrapResult( vkCreateBuffer( dev->vk.device, &stageBufferCreateInfo, NULL, &tempBuffer.buffer ) ); + + VmaAllocationInfo allocationInfo = {}; + VmaAllocationCreateInfo allocInfo = {}; + allocInfo.flags |= VMA_ALLOCATION_CREATE_MAPPED_BIT; + vmaAllocateMemoryForBuffer( dev->vk.vmaAllocator, tempBuffer.buffer, &allocInfo, &tempBuffer.alloc, &allocationInfo ); + vmaBindBufferMemory2( dev->vk.vmaAllocator, tempBuffer.alloc, 0, tempBuffer.buffer, NULL ); + + req->vk.alloc = tempBuffer.alloc; + req->cpuMapping = allocationInfo.pMappedData; + req->byteOffset = 0; + req->vk.buffer = tempBuffer.buffer; + + arrpush( res->vk.cmdSets[res->activeSet].temporary, tempBuffer ); + } ) ); + return true; +} + + +void RI_ResourceBeginCopyBuffer( struct RIDevice_s *device, struct RIResourceUploader_s *res, struct RIResourceBufferTransaction_s *trans ) { + __ResolveStageBuffer(device, res, trans->numBytes, &trans->req); + trans->data = (uint8_t *)trans->req.cpuMapping + trans->req.byteOffset; +} + +void RI_ResourceEndCopyBuffer( struct RIDevice_s *device, struct RIResourceUploader_s *res, struct RIResourceBufferTransaction_s *trans ) { + GPU_VULKAN_BLOCK( device->renderer, ( { + VkBufferCopy copyBuffer = {}; + copyBuffer.size = trans->numBytes; + copyBuffer.dstOffset = trans->offset; + copyBuffer.srcOffset = trans->req.byteOffset; + vkCmdCopyBuffer( res->vk.cmdSets[res->activeSet].cmdBuffer, trans->req.vk.buffer, trans->vk.buffer, 1, ©Buffer ); + } ) ); +} + + +void RI_ResourceBeginCopyTexture(struct RIDevice_s* device, struct RIResourceUploader_s *res, struct RIResourceTextureTransaction_s *trans ) { + const uint64_t alignedRowPitch = Q_ALIGN_TO( trans->rowPitch, device->physicalAdapter.uploadBufferTextureRowAlignment ); + const uint64_t alignedSlicePitch = Q_ALIGN_TO( trans->sliceNum * alignedRowPitch, device->physicalAdapter.uploadBufferTextureSliceAlignment ); + trans->alignRowPitch = alignedRowPitch; + trans->alignSlicePitch = alignedSlicePitch; + __ResolveStageBuffer(device, res, alignedSlicePitch, &trans->req); + trans->data = (uint8_t *)trans->req.cpuMapping + trans->req.byteOffset; +} + +void RI_ResourceSubmit(struct RIDevice_s* device, struct RIResourceUploader_s *res) { + //arrsetlen(commandSets[activeSet].seenBuffers, 0); + //arrsetlen(commandSets[activeSet].seenTextures, 0); + + //R_UploadEndCommandSet( activeSet ); + + res->activeSet = ( res->activeSet + 1 ) % RI_RESOURCE_NUM_COMMAND_SETS; + if( res->syncIndex >= RI_RESOURCE_NUM_COMMAND_SETS ) { + //struct command_set_s *set = &commandSets[activeSet]; + //rsh.nri.coreI.Wait( uploadFence, 1 + syncIndex - NUMBER_COMMAND_SETS ); + //rsh.nri.coreI.ResetCommandAllocator( set->allocator ); + //for( size_t i = 0; i < arrlen( set->temporary ); i++ ) { + // rsh.nri.coreI.DestroyBuffer( set->temporary[i].buffer ); + // rsh.nri.coreI.FreeMemory( set->temporary[i].memory ); + //} + //arrsetlen( set->temporary, 0 ); + } + __BeginNewCommandSet(device, res); + +} + +void RI_ResourceEndCopyTexture( struct RIDevice_s *device, struct RIResourceUploader_s *res, struct RIResourceTextureTransaction_s *trans ) +{ + GPU_VULKAN_BLOCK( device->renderer, ( { + const struct RIFormatProps_s *formatProps = GetRIFormatProps( trans->format ); + VkBufferImageCopy copyReq = {}; + copyReq.bufferOffset = trans->req.byteOffset; + copyReq.bufferRowLength = ( trans->alignRowPitch / formatProps->stride ) * formatProps->blockWidth; + copyReq.bufferImageHeight = ( trans->alignSlicePitch / trans->alignRowPitch ) * formatProps->blockWidth; + copyReq.imageOffset.x = trans->x; + copyReq.imageOffset.y = trans->y; + copyReq.imageOffset.z = trans->z; + copyReq.imageExtent.width = trans->width; + copyReq.imageExtent.height = trans->height; + copyReq.imageExtent.depth = trans->depth; + copyReq.imageSubresource.mipLevel = trans->mipOffset; + copyReq.imageSubresource.layerCount = 1; + copyReq.imageSubresource.baseArrayLayer = trans->arrayOffset; + copyReq.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + vkCmdCopyBufferToImage( res->vk.cmdSets[res->activeSet].cmdBuffer, trans->req.vk.buffer, trans->vk.image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ©Req ); + } ) ); +} diff --git a/source/ref_nri/ri_resource_upload.h b/source/ref_nri/ri_resource_upload.h new file mode 100644 index 0000000000..6594b86225 --- /dev/null +++ b/source/ref_nri/ri_resource_upload.h @@ -0,0 +1,110 @@ + +#ifndef RI_RESOURCE_UPLOAD_H +#define RI_RESOURCE_UPLOAD_H + +#define RI_RESOURCE_NUM_COMMAND_SETS 4 +#define RI_RESOURCE_STAGE_SIZE (8 * MB_TO_BYTE) + +#include "ri_types.h" +#include "qtypes.h" + +struct RIResourceReq { + uint64_t byteOffset; + void *cpuMapping; + union { +#if ( DEVICE_IMPL_VULKAN ) + struct { + VkBuffer buffer; + struct VmaAllocation_T* alloc; + } vk; +#endif + }; +}; + +struct RIResourceUploader_s{ + struct RIQueue_s* copyQueue; + size_t tailOffset; + size_t remaningSpace; + size_t reservedSpacePerSet[RI_RESOURCE_NUM_COMMAND_SETS]; + uint32_t activeSet; + uint32_t syncIndex; + union { +#if ( DEVICE_IMPL_VULKAN ) + struct { + struct VmaAllocation_T* stageAlloc; + VkBuffer stageBuffer; + void *pMappedData; + + struct { + VkCommandPool cmdPool; + VkCommandBuffer cmdBuffer; + struct RI_VK_TempBuffers { + VkBuffer buffer; + struct VmaAllocation_T *alloc; + } *temporary; + } cmdSets[RI_RESOURCE_NUM_COMMAND_SETS]; + } vk; +#endif + }; +}; + +void RI_InitResourceUploader( struct RIDevice_s *device, struct RIResourceUploader_s *resource ); + +struct RIResourceBufferTransaction_s { + union { +#if ( DEVICE_IMPL_VULKAN ) + struct { + VkBuffer buffer; + } vk; +#endif + }; + size_t numBytes; + size_t offset; + + // begin mapping + void *data; + struct RIResourceReq req; +}; + +void RI_ResourceBeginCopyBuffer( struct RIDevice_s *device, struct RIResourceUploader_s *res, struct RIResourceBufferTransaction_s *trans ); +void RI_ResourceEndCopyBuffer( struct RIDevice_s *device, struct RIResourceUploader_s *res, struct RIResourceBufferTransaction_s *trans ); + +struct RIResourceTextureTransaction_s{ + + union { +#if ( DEVICE_IMPL_VULKAN ) + struct { + VkImage image; + } vk; +#endif + }; + + // https://github.com/microsoft/DirectXTex/wiki/Image + uint32_t format; // RI_Format_e + uint32_t sliceNum; + uint32_t rowPitch; + + uint16_t x; + uint16_t y; + uint16_t z; + uint32_t width; + uint32_t height; + uint32_t depth; + + uint32_t arrayOffset; + uint32_t mipOffset; + + // begin mapping + void *data; + uint32_t alignRowPitch; + uint32_t alignSlicePitch; + struct RIResourceReq req; +}; + +void RI_ResourceBeginCopyTexture(struct RIDevice_s* device, struct RIResourceUploader_s *res, struct RIResourceTextureTransaction_s *trans ); +void RI_ResourceEndCopyTexture(struct RIDevice_s* device, struct RIResourceUploader_s *res, struct RIResourceTextureTransaction_s *trans ); + +void RI_ResourceSubmit(struct RIDevice_s* device, struct RIResourceUploader_s *res); + + +#endif diff --git a/source/ref_nri/ri_swapchain.c b/source/ref_nri/ri_swapchain.c index 54cbcac25d..d9f9ba223d 100644 --- a/source/ref_nri/ri_swapchain.c +++ b/source/ref_nri/ri_swapchain.c @@ -1,4 +1,5 @@ #include "ri_swapchain.h" +#include "ri_types.h" #if ( DEVICE_IMPL_VULKAN ) @@ -24,8 +25,6 @@ static uint32_t __priority_BT2020_G2084_10BIT(const VkSurfaceFormatKHR* surface) ((surface->colorSpace == VK_COLOR_SPACE_HDR10_ST2084_EXT) << 1); } - - #endif int InitRISwapchain(struct RIDevice_s* dev, struct RISwapchainDesc_s* init, struct RISwapchain_s* swapchain) { @@ -33,21 +32,10 @@ int InitRISwapchain(struct RIDevice_s* dev, struct RISwapchainDesc_s* init, stru assert(init); assert(swapchain); assert( init->imageCount <= Q_ARRAY_COUNT( swapchain->vk.images ) ); - swapchain->imageCount = init->imageCount; + swapchain->width = init->width; + swapchain->height = init->height; VkResult result = VK_SUCCESS; GPU_VULKAN_BLOCK(dev->renderer, ({ - for(size_t i = 0; i < init->imageCount; i++) { - VkSemaphoreCreateInfo createInfo = {VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO}; - VkSemaphoreTypeCreateInfo timelineCreateInfo = {VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO}; - timelineCreateInfo.semaphoreType = VK_SEMAPHORE_TYPE_BINARY; - R_VK_ADD_STRUCT(&createInfo, &timelineCreateInfo); - - result = vkCreateSemaphore(dev->vk.device, &createInfo, NULL, &swapchain->vk.imageAcquireSem[i]); - VK_WrapResult(result); - - result = vkCreateSemaphore(dev->vk.device, &createInfo, NULL, &swapchain->vk.finishSem[i]); - VK_WrapResult(result); - } switch(init->windowHandle->type) { @@ -190,27 +178,29 @@ int InitRISwapchain(struct RIDevice_s* dev, struct RISwapchainDesc_s* init, stru result = vkCreateSwapchainKHR( dev->vk.device, &swapChainCreateInfo, NULL, &swapchain->vk.swapchain); } - VkImage* imageHandles = NULL; { uint32_t imageNum = 0; vkGetSwapchainImagesKHR(dev->vk.device, swapchain->vk.swapchain, &imageNum, NULL); - imageHandles = malloc(imageNum * sizeof(VkImage)); - vkGetSwapchainImagesKHR(dev->vk.device, swapchain->vk.swapchain, &imageNum, imageHandles); - - for(uint32_t i = 0; i < imageNum; i++) { - struct RITexture_s* tex = &swapchain->images[i]; - tex->vk.image = imageHandles[i]; - tex->type = RI_TEXTURE_2D; - tex->width = init->width; - tex->height = init->height; - tex->depth = 1; - tex->mipNum = 1; - tex->layerNum = 1; - tex->sampleNum = 1; + assert(imageNum >= RI_MAX_SWAPCHAIN_IMAGES); + vkGetSwapchainImagesKHR(dev->vk.device, swapchain->vk.swapchain, &imageNum, swapchain->vk.images); + swapchain->imageCount = imageNum; + swapchain->format = VKToRIFormat(selectedSurf->format); + + for(size_t i = 0; i < imageNum; i++) { + VkSemaphoreCreateInfo createInfo = {VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO}; + VkSemaphoreTypeCreateInfo timelineCreateInfo = {VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO}; + timelineCreateInfo.semaphoreType = VK_SEMAPHORE_TYPE_BINARY; + R_VK_ADD_STRUCT(&createInfo, &timelineCreateInfo); + + + result = vkCreateSemaphore(dev->vk.device, &createInfo, NULL, &swapchain->vk.imageAcquireSem[i]); + VK_WrapResult(result); + + result = vkCreateSemaphore(dev->vk.device, &createInfo, NULL, &swapchain->vk.finishSem[i]); + VK_WrapResult(result); } } free(supportedPresentMode); free(surfaceFormats); - free(imageHandles); return RI_SUCCESS; } diff --git a/source/ref_nri/ri_types.h b/source/ref_nri/ri_types.h index 19baa38193..63b35650bd 100644 --- a/source/ref_nri/ri_types.h +++ b/source/ref_nri/ri_types.h @@ -1,5 +1,4 @@ - #ifndef RI_TYPES_H #define RI_TYPES_H @@ -7,6 +6,10 @@ #include "math/qmath.h" #include "qtypes.h" +#define RI_MAX_SWAPCHAIN_IMAGES 8 +#define RI_NUMBER_FRAMES_FLIGHT 3 + + #define DEVICE_SUPPORT_VULKAN #ifdef DEVICE_SUPPORT_VULKAN @@ -142,6 +145,7 @@ enum RITextureViewType_s { }; + enum RITextureUsageBits_e { RI_USAGE_NONE = 0, RI_USAGE_SHADER_RESOURCE = 0x1, @@ -204,7 +208,6 @@ enum RIBufferUsage_e { RI_BUFFER_USAGE_BINDING_TABLE = 0x80, RI_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPT = 0x100, RI_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE = 0x200, - }; enum RITextureType_e { @@ -227,41 +230,56 @@ enum RIWindowType_e { RI_WINDOW_WAYLAND }; -struct RIHeap_s { - -}; - -struct RIMemory_s { +struct RIBufferHandle_s { union { #if(DEVICE_IMPL_VULKAN) struct { - struct VmaAllocation_T* vmaAlloc; // pointering to owning allocation + VkBuffer buffer; } vk; #endif }; +}; +enum RIDescriptorType_e { + RI_DESCRIPTOR_NONE, + RI_DESCRIPTOR_BUFFER_VIEW, + RI_DESCRIPTOR_IMAGE_VIEW, + RI_DESCRIPTOR_SAMPLER, + RI_DESCRIPTOR_ACCELERATION_STRUCTURE, }; -struct RIBuffer_s { +struct RIDescriptor_s { union { - #if(DEVICE_IMPL_VULKAN) - struct { - VkBuffer buffer; - } vk; - #endif +#if ( DEVICE_IMPL_VULKAN ) + struct { + uint8_t type; // RI_DescriptorTypeVK + union { + struct { + VkImageView view; + } image; + struct { + } buffer; + struct { + VkSampler sampler; + } sampler; + }; + } vk; +#endif }; + uint32_t cookie; }; -struct RITexture_s { - uint8_t type; // RITextureType_e - uint8_t mipNum; - uint8_t sampleNum; - uint16_t width; - uint16_t height; - uint16_t depth; - uint16_t layerNum; +struct RICmdHandle_s { + union { +#if ( DEVICE_IMPL_VULKAN ) + struct { + } vk; +#endif + }; +}; +struct RITextureHandle_s { union { #if(DEVICE_IMPL_VULKAN) struct { @@ -269,19 +287,22 @@ struct RITexture_s { } vk; #endif }; - }; + struct RISwapchain_s { uint16_t imageCount; - struct RITexture_s images[8]; + uint16_t width; + uint16_t height; + uint32_t format; // RI_Format_e union { #if(DEVICE_IMPL_VULKAN) struct { VkSwapchainKHR swapchain; VkSurfaceKHR surface; - VkSemaphore imageAcquireSem[8]; - VkSemaphore finishSem[8]; + VkImage images[RI_MAX_SWAPCHAIN_IMAGES]; + VkSemaphore imageAcquireSem[RI_MAX_SWAPCHAIN_IMAGES]; + VkSemaphore finishSem[RI_MAX_SWAPCHAIN_IMAGES]; } vk; #endif }; @@ -311,7 +332,6 @@ struct RIQueue_s { }; }; - struct RIRenderer_s { uint8_t api; // RIDeviceAPI_e union { @@ -617,6 +637,4 @@ struct RIDevice_s { #endif }; }; - - #endif