@@ -248,7 +248,11 @@ pl_resource_new_frame(void)
248248 plCommandBuffer * ptCommandBuffer = gptGfx -> request_command_buffer (ptCmdPool , "resource update" );
249249 gptGfx -> begin_command_recording (ptCommandBuffer , NULL );
250250 plBlitEncoder * ptBlitEncoder = gptGfx -> begin_blit_pass (ptCommandBuffer );
251- gptGfx -> pipeline_barrier_blit (ptBlitEncoder , PL_PIPELINE_STAGE_VERTEX_SHADER | PL_PIPELINE_STAGE_COMPUTE_SHADER | PL_PIPELINE_STAGE_TRANSFER , PL_ACCESS_SHADER_READ | PL_ACCESS_TRANSFER_READ , PL_PIPELINE_STAGE_TRANSFER , PL_ACCESS_TRANSFER_WRITE );
251+ gptGfx -> pipeline_barrier_blit (ptBlitEncoder ,
252+ PL_PIPELINE_STAGE_VERTEX_SHADER | PL_PIPELINE_STAGE_COMPUTE_SHADER | PL_PIPELINE_STAGE_TRANSFER ,
253+ PL_ACCESS_SHADER_READ | PL_ACCESS_TRANSFER_READ ,
254+ PL_PIPELINE_STAGE_TRANSFER ,
255+ PL_ACCESS_TRANSFER_WRITE );
252256
253257 for (uint32_t i = 0 ; i < uJobCount ; i ++ )
254258 {
@@ -260,7 +264,11 @@ pl_resource_new_frame(void)
260264 gptGfx -> generate_mipmaps (ptBlitEncoder , ptJob -> tTexture );
261265 }
262266
263- gptGfx -> pipeline_barrier_blit (ptBlitEncoder , PL_PIPELINE_STAGE_TRANSFER , PL_ACCESS_TRANSFER_WRITE , PL_PIPELINE_STAGE_VERTEX_SHADER | PL_PIPELINE_STAGE_COMPUTE_SHADER | PL_PIPELINE_STAGE_TRANSFER , PL_ACCESS_SHADER_READ | PL_ACCESS_TRANSFER_READ );
267+ gptGfx -> pipeline_barrier_blit (ptBlitEncoder ,
268+ PL_PIPELINE_STAGE_TRANSFER ,
269+ PL_ACCESS_TRANSFER_WRITE ,
270+ PL_PIPELINE_STAGE_VERTEX_SHADER | PL_PIPELINE_STAGE_COMPUTE_SHADER | PL_PIPELINE_STAGE_TRANSFER ,
271+ PL_ACCESS_SHADER_READ | PL_ACCESS_TRANSFER_READ );
264272 gptGfx -> end_blit_pass (ptBlitEncoder );
265273 gptGfx -> end_command_recording (ptCommandBuffer );
266274 gptGfx -> submit_command_buffer (ptCommandBuffer , NULL );
@@ -318,7 +326,7 @@ pl_resource_load_ex(const char* pcName, plResourceLoadFlags tFlags, uint8_t* puO
318326
319327 uint8_t * puFileData = puOriginalFileData ;
320328
321- // load file data
329+ // load file data if not manually loaded
322330 if (puFileData == NULL )
323331 {
324332 szFileByteSize = gptVfs -> get_file_size_str (pcContainerFileName ); //-V763
@@ -350,11 +358,10 @@ pl_resource_load_ex(const char* pcName, plResourceLoadFlags tFlags, uint8_t* puO
350358 tResource .puFileData = puFileData ;
351359 }
352360
353-
354361 strncpy (tResource .acName , pcName , PL_MAX_NAME_LENGTH );
355362 strncpy (tResource .acContainerFileName , pcContainerFileName , PL_MAX_NAME_LENGTH );
356363
357- // find our resource a home
364+ // find our resource a home slot
358365 uint64_t uIndex = pl_hm_get_free_index (& gptResourceManager -> tNameHashmap );
359366 if (uIndex == PL_DS_HASH_INVALID )
360367 {
@@ -407,7 +414,6 @@ pl_resource_load_ex(const char* pcName, plResourceLoadFlags tFlags, uint8_t* puO
407414 int iTextureWidth = 0 ;
408415 int iTextureHeight = 0 ;
409416 int iTextureChannels = 0 ;
410- plFormat tTextureFormat = PL_FORMAT_UNKNOWN ;
411417
412418 if (tImageInfo .bHDR )
413419 {
@@ -427,7 +433,7 @@ pl_resource_load_ex(const char* pcName, plResourceLoadFlags tFlags, uint8_t* puO
427433 else if (gptResourceManager -> tStagingBuffer .szOffset + szRequiredStagingSize >= gptResourceManager -> tStagingBuffer .szSize )
428434 {
429435 pl_resource_new_frame ();
430- pl_resource_new_frame ();
436+ pl_resource_new_frame (); // this one destroys the staging buffer
431437 pl__resource_create_staging_buffer (szRequiredStagingSize );
432438 }
433439
@@ -459,7 +465,7 @@ pl_resource_load_ex(const char* pcName, plResourceLoadFlags tFlags, uint8_t* puO
459465 else if (gptResourceManager -> tStagingBuffer .szOffset + szRequiredStagingSize >= gptResourceManager -> tStagingBuffer .szSize )
460466 {
461467 pl_resource_new_frame ();
462- pl_resource_new_frame ();
468+ pl_resource_new_frame (); // this one destroys the staging buffer
463469 pl__resource_create_staging_buffer (szRequiredStagingSize );
464470 }
465471
@@ -470,8 +476,6 @@ pl_resource_load_ex(const char* pcName, plResourceLoadFlags tFlags, uint8_t* puO
470476
471477 gptImage -> free (puRawBytes );
472478
473- tTextureFormat = PL_FORMAT_R16G16B16A16_UNORM ;
474-
475479 // create texture
476480 const plTextureDesc tTextureDesc = {
477481 .tDimensions = {(float )tImageInfo .iWidth , (float )tImageInfo .iHeight , 1 },
@@ -484,6 +488,178 @@ pl_resource_load_ex(const char* pcName, plResourceLoadFlags tFlags, uint8_t* puO
484488
485489 tResource .tTexture = gptGfx -> create_texture (ptDevice , & tTextureDesc , & ptTexture );
486490 }
491+ else if (bAttemptCompression )
492+ {
493+ unsigned char * puRawBytes = gptImage -> load ((unsigned char * )puFileData , (int )szFileByteSize , & iTextureWidth , & iTextureHeight , & iTextureChannels , 4 );
494+
495+ if (bResizeNeeded )
496+ {
497+ unsigned char * puOldRawBytes = puRawBytes ;
498+ puRawBytes = stbir_resize_uint8_linear (puRawBytes , iTextureWidth , iTextureHeight , 0 , NULL , tImageInfo .iWidth , tImageInfo .iHeight , 0 , STBIR_RGBA );
499+ PL_ASSERT (puRawBytes );
500+ gptImage -> free (puOldRawBytes );
501+ }
502+
503+ // create texture
504+ const plTextureDesc tTextureDesc = {
505+ .tDimensions = {(float )tImageInfo .iWidth , (float )tImageInfo .iHeight , 1 },
506+ .tFormat = PL_FORMAT_BC2_UNORM ,
507+ .uLayers = 1 ,
508+ .uMips = 0 ,
509+ .tType = PL_TEXTURE_TYPE_2D ,
510+ .tUsage = PL_TEXTURE_USAGE_SAMPLED
511+ };
512+
513+ tResource .tTexture = gptGfx -> create_texture (ptDevice , & tTextureDesc , & ptTexture );
514+
515+ // choose allocator
516+ plDeviceMemoryAllocatorI * ptAllocator = gptResourceManager -> ptLocalBuddyAllocator ;
517+ if (ptTexture -> tMemoryRequirements .ulSize > gptGpuAllocators -> get_buddy_block_size ())
518+ ptAllocator = gptResourceManager -> ptLocalDedicatedAllocator ;
519+
520+ // allocate memory
521+ const plDeviceMemoryAllocation tAllocation = ptAllocator -> allocate (ptAllocator -> ptInst ,
522+ ptTexture -> tMemoryRequirements .uMemoryTypeBits ,
523+ ptTexture -> tMemoryRequirements .ulSize ,
524+ ptTexture -> tMemoryRequirements .ulAlignment ,
525+ pl_temp_allocator_sprintf (& gptResourceManager -> tTempAllocator , "texture alloc %s" , pcName ));
526+ pl_temp_allocator_reset (& gptResourceManager -> tTempAllocator );
527+
528+ // bind memory
529+ gptGfx -> bind_texture_to_memory (ptDevice , tResource .tTexture , & tAllocation );
530+
531+ plDxtInfo tDxtInfoOriginal = {
532+ .tFlags = PL_DXT_FLAGS_HIGH_QUALITY ,
533+ .uWidth = (uint32_t )tImageInfo .iWidth ,
534+ .uHeight = (uint32_t )tImageInfo .iHeight ,
535+ .uChannels = 4 ,
536+ .puData = puRawBytes
537+ };
538+ size_t szRequiredStagingSize = 0 ;
539+ gptDxt -> compress (& tDxtInfoOriginal , NULL , & szRequiredStagingSize );
540+
541+
542+ if (!gptGfx -> is_buffer_valid (ptDevice , gptResourceManager -> tStagingBuffer .tStagingBufferHandle ))
543+ pl__resource_create_staging_buffer (szRequiredStagingSize );
544+ else if (gptResourceManager -> tStagingBuffer .szOffset + szRequiredStagingSize >= gptResourceManager -> tStagingBuffer .szSize )
545+ {
546+ pl_resource_new_frame ();
547+ pl_resource_new_frame (); // this one destroys the staging buffer
548+ pl__resource_create_staging_buffer (szRequiredStagingSize );
549+ }
550+
551+
552+
553+
554+ plBuffer * ptStagingBuffer = gptGfx -> get_buffer (ptDevice , gptResourceManager -> tStagingBuffer .tStagingBufferHandle );
555+
556+ gptDxt -> compress (& tDxtInfoOriginal , (uint8_t * )& ptStagingBuffer -> tMemoryAllocation .pHostMapped [szStagingOffset ], & szRequiredStagingSize );
557+
558+ size_t szCurrentSize = szRequiredStagingSize ;
559+ size_t szMaxBufferSize = tImageInfo .iWidth * tImageInfo .iHeight * 4 ;
560+ uint8_t * auWorkingBuffer [2 ] = {0 };
561+ auWorkingBuffer [0 ] = PL_ALLOC (szMaxBufferSize );
562+ auWorkingBuffer [1 ] = puRawBytes ;
563+ memset (auWorkingBuffer [0 ], 0 , szMaxBufferSize );
564+
565+
566+
567+ const plBufferImageCopy tBufferImageCopy0 = {
568+ .uImageWidth = (uint32_t )tImageInfo .iWidth ,
569+ .uImageHeight = (uint32_t )tImageInfo .iHeight ,
570+ .uImageDepth = 1 ,
571+ .uLayerCount = 1 ,
572+ .szBufferOffset = szStagingOffset ,
573+ .uMipLevel = 0
574+ };
575+
576+ plCommandPool * ptCmdPool = gptResourceManager -> atCmdPools [gptGfx -> get_current_frame_index ()];
577+ plCommandBuffer * ptCommandBuffer = gptGfx -> request_command_buffer (ptCmdPool , "resource update" );
578+ gptGfx -> begin_command_recording (ptCommandBuffer , NULL );
579+ plBlitEncoder * ptBlitEncoder = gptGfx -> begin_blit_pass (ptCommandBuffer );
580+ gptGfx -> set_texture_usage (ptBlitEncoder , tResource .tTexture , PL_TEXTURE_USAGE_SAMPLED , 0 );
581+
582+ gptGfx -> copy_buffer_to_texture (ptBlitEncoder , gptResourceManager -> tStagingBuffer .tStagingBufferHandle , tResource .tTexture , 1 , & tBufferImageCopy0 );
583+
584+ szStagingOffset += szCurrentSize ;
585+
586+ for (uint32_t uMipLevel = 1 ; uMipLevel < ptTexture -> tDesc .uMips ; uMipLevel ++ )
587+ {
588+
589+ uint8_t * puSrcBuffer = auWorkingBuffer [uMipLevel % 2 ];
590+ uint8_t * puDstBuffer = auWorkingBuffer [(uMipLevel + 1 ) % 2 ];
591+
592+ int iCurrentWidth = (int )tImageInfo .iWidth / ((1 << (int )uMipLevel ));
593+ int iCurrentHeight = (int )tImageInfo .iHeight / ((1 << (int )uMipLevel ));
594+
595+ int iLastWidth = iCurrentWidth * 2 ;
596+ int iLastHeight = iCurrentHeight * 2 ;
597+
598+ szCurrentSize = 0 ;
599+
600+ // manual mip mapping
601+ for (uint32_t i = 0 ; i < (uint32_t )iCurrentWidth ; i ++ )
602+ {
603+ for (uint32_t j = 0 ; j < (uint32_t )iCurrentHeight ; j ++ )
604+ {
605+ uint32_t uSrcOriginX = i * 2 ;
606+ uint32_t uSrcOriginY = j * 2 ;
607+
608+ uint8_t * ptPixel0 = & puSrcBuffer [uSrcOriginY * iLastWidth * 4 + uSrcOriginX * 4 ];
609+ uint8_t * ptPixel1 = & puSrcBuffer [uSrcOriginY * iLastWidth * 4 + (uSrcOriginX + 1 ) * 4 ];
610+ uint8_t * ptPixel2 = & puSrcBuffer [(uSrcOriginY + 1 ) * iLastWidth * 4 + uSrcOriginX * 4 ];
611+ uint8_t * ptPixel3 = & puSrcBuffer [(uSrcOriginY + 1 ) * iLastWidth * 4 + (uSrcOriginX + 1 ) * 4 ];
612+
613+ uint8_t uRed = (ptPixel0 [0 ] + ptPixel1 [0 ] + ptPixel2 [0 ] + ptPixel3 [0 ]) / 4 ;
614+ uint8_t uGreen = (ptPixel0 [1 ] + ptPixel1 [1 ] + ptPixel2 [1 ] + ptPixel3 [1 ]) / 4 ;
615+ uint8_t uBlue = (ptPixel0 [2 ] + ptPixel1 [2 ] + ptPixel2 [2 ] + ptPixel3 [2 ]) / 4 ;
616+ uint8_t uAlpha = (ptPixel0 [3 ] + ptPixel1 [3 ] + ptPixel2 [3 ] + ptPixel3 [3 ]) / 4 ;
617+
618+
619+ puDstBuffer [j * iCurrentWidth * 4 + i * 4 + 0 ] = uRed ;
620+ puDstBuffer [j * iCurrentWidth * 4 + i * 4 + 1 ] = uGreen ;
621+ puDstBuffer [j * iCurrentWidth * 4 + i * 4 + 2 ] = uBlue ;
622+ puDstBuffer [j * iCurrentWidth * 4 + i * 4 + 3 ] = uAlpha ;
623+ }
624+ }
625+
626+ // compression
627+ {
628+ plDxtInfo tDxtInfo = {
629+ .tFlags = PL_DXT_FLAGS_HIGH_QUALITY ,
630+ .uWidth = (uint32_t )iCurrentWidth ,
631+ .uHeight = (uint32_t )iCurrentHeight ,
632+ .uChannels = 4 ,
633+ .puData = puDstBuffer
634+ };
635+ szRequiredStagingSize = 0 ;
636+ gptDxt -> compress (& tDxtInfo , NULL , & szRequiredStagingSize );
637+ gptDxt -> compress (& tDxtInfo , (uint8_t * )& ptStagingBuffer -> tMemoryAllocation .pHostMapped [szStagingOffset ], & szRequiredStagingSize );
638+ szCurrentSize = szRequiredStagingSize ;
639+ }
640+
641+ const plBufferImageCopy tBufferImageCopy = {
642+ .uImageWidth = (uint32_t )iCurrentWidth ,
643+ .uImageHeight = (uint32_t )iCurrentHeight ,
644+ .uImageDepth = 1 ,
645+ .uLayerCount = 1 ,
646+ .szBufferOffset = szStagingOffset ,
647+ .uMipLevel = uMipLevel
648+ };
649+
650+ gptGfx -> copy_buffer_to_texture (ptBlitEncoder , gptResourceManager -> tStagingBuffer .tStagingBufferHandle , tResource .tTexture , 1 , & tBufferImageCopy );
651+ szStagingOffset += szCurrentSize ;
652+ }
653+
654+ gptGfx -> end_blit_pass (ptBlitEncoder );
655+ gptGfx -> end_command_recording (ptCommandBuffer );
656+ gptGfx -> submit_command_buffer (ptCommandBuffer , NULL );
657+ gptGfx -> wait_on_command_buffer (ptCommandBuffer );
658+ gptGfx -> return_command_buffer (ptCommandBuffer );
659+
660+ gptImage -> free (puRawBytes );
661+ PL_FREE (auWorkingBuffer [0 ]);
662+ }
487663 else
488664 {
489665 unsigned char * puRawBytes = gptImage -> load ((unsigned char * )puFileData , (int )szFileByteSize , & iTextureWidth , & iTextureHeight , & iTextureChannels , 4 );
@@ -502,7 +678,7 @@ pl_resource_load_ex(const char* pcName, plResourceLoadFlags tFlags, uint8_t* puO
502678 else if (gptResourceManager -> tStagingBuffer .szOffset + szRequiredStagingSize >= gptResourceManager -> tStagingBuffer .szSize )
503679 {
504680 pl_resource_new_frame ();
505- pl_resource_new_frame ();
681+ pl_resource_new_frame (); // this one destroys the staging buffer
506682 pl__resource_create_staging_buffer (szRequiredStagingSize );
507683 }
508684
@@ -525,35 +701,39 @@ pl_resource_load_ex(const char* pcName, plResourceLoadFlags tFlags, uint8_t* puO
525701
526702 tResource .tTexture = gptGfx -> create_texture (ptDevice , & tTextureDesc , & ptTexture );
527703 }
704+
705+ if (!bAttemptCompression )
706+ {
528707
529- // choose allocator
530- plDeviceMemoryAllocatorI * ptAllocator = gptResourceManager -> ptLocalBuddyAllocator ;
531- if (ptTexture -> tMemoryRequirements .ulSize > gptGpuAllocators -> get_buddy_block_size ())
532- ptAllocator = gptResourceManager -> ptLocalDedicatedAllocator ;
533-
534- // allocate memory
535- const plDeviceMemoryAllocation tAllocation = ptAllocator -> allocate (ptAllocator -> ptInst ,
536- ptTexture -> tMemoryRequirements .uMemoryTypeBits ,
537- ptTexture -> tMemoryRequirements .ulSize ,
538- ptTexture -> tMemoryRequirements .ulAlignment ,
539- pl_temp_allocator_sprintf (& gptResourceManager -> tTempAllocator , "texture alloc %s" , pcName ));
540- pl_temp_allocator_reset (& gptResourceManager -> tTempAllocator );
541-
542- // bind memory
543- gptGfx -> bind_texture_to_memory (ptDevice , tResource .tTexture , & tAllocation );
544-
545- plTextureUploadJob tUpload = {
546- .tTexture = tResource .tTexture ,
547- .tBufferImageCopy = {
548- .uImageWidth = (uint32_t )ptTexture -> tDesc .tDimensions .x ,
549- .uImageHeight = (uint32_t )ptTexture -> tDesc .tDimensions .y ,
550- .uImageDepth = 1 ,
551- .uLayerCount = 1 ,
552- .szBufferOffset = szStagingOffset
553- },
554- .bGenerateMips = bGenerateMips
555- };
556- pl_sb_push (gptResourceManager -> sbtTextureUploadJobs , tUpload );
708+ // choose allocator
709+ plDeviceMemoryAllocatorI * ptAllocator = gptResourceManager -> ptLocalBuddyAllocator ;
710+ if (ptTexture -> tMemoryRequirements .ulSize > gptGpuAllocators -> get_buddy_block_size ())
711+ ptAllocator = gptResourceManager -> ptLocalDedicatedAllocator ;
712+
713+ // allocate memory
714+ const plDeviceMemoryAllocation tAllocation = ptAllocator -> allocate (ptAllocator -> ptInst ,
715+ ptTexture -> tMemoryRequirements .uMemoryTypeBits ,
716+ ptTexture -> tMemoryRequirements .ulSize ,
717+ ptTexture -> tMemoryRequirements .ulAlignment ,
718+ pl_temp_allocator_sprintf (& gptResourceManager -> tTempAllocator , "texture alloc %s" , pcName ));
719+ pl_temp_allocator_reset (& gptResourceManager -> tTempAllocator );
720+
721+ // bind memory
722+ gptGfx -> bind_texture_to_memory (ptDevice , tResource .tTexture , & tAllocation );
723+
724+ plTextureUploadJob tUpload = {
725+ .tTexture = tResource .tTexture ,
726+ .tBufferImageCopy = {
727+ .uImageWidth = (uint32_t )ptTexture -> tDesc .tDimensions .x ,
728+ .uImageHeight = (uint32_t )ptTexture -> tDesc .tDimensions .y ,
729+ .uImageDepth = 1 ,
730+ .uLayerCount = 1 ,
731+ .szBufferOffset = szStagingOffset
732+ },
733+ .bGenerateMips = bGenerateMips
734+ };
735+ pl_sb_push (gptResourceManager -> sbtTextureUploadJobs , tUpload );
736+ }
557737 }
558738 break ;
559739 }
0 commit comments