image load and save

pull/8/head
cosmonaut 2020-12-27 22:45:12 -08:00
parent 39ec13501a
commit 6e59750ff2
7 changed files with 14808 additions and 2 deletions

View File

@ -45,12 +45,14 @@ add_definitions(
add_library(Refresh add_library(Refresh
# Public Headers # Public Headers
include/Refresh.h include/Refresh.h
include/Refresh_Image.h
# Internal Headers # Internal Headers
src/Refresh_Driver.h src/Refresh_Driver.h
src/Refresh_Driver_Vulkan_vkfuncs.h src/Refresh_Driver_Vulkan_vkfuncs.h
# Source Files # Source Files
src/Refresh.c src/Refresh.c
src/Refresh_Driver_Vulkan.c src/Refresh_Driver_Vulkan.c
src/Refresh_Image.c
) )
# Build flags # Build flags

91
include/Refresh_Image.h Normal file
View File

@ -0,0 +1,91 @@
/* Refresh - XNA-inspired 3D Graphics Library with modern capabilities
*
* Copyright (c) 2020 Ethan Lee and Evan Hemsley
*
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from
* the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software in a
* product, an acknowledgment in the product documentation would be
* appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source distribution.
*
* Ethan "flibitijibibo" Lee <flibitijibibo@flibitijibibo.com>
* Evan "cosmonaut" Hemsley <evan@moonside.games>
*
* This source file is heavily borrowed from FNA3D_Image.h and was originally
* written by Ethan Lee.
*/
#ifndef REFRESH_IMAGE_H
#define REFRESH_IMAGE_H
#ifdef _WIN32
#define REFRESHAPI __declspec(dllexport)
#define REFRESHCALL __cdecl
#else
#define REFRESHAPI
#define REFRESHCALL
#endif
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/* Decodes PNG data into raw RGBA8 texture data.
*
* w: Filled with the width of the image.
* h: Filled with the height of the image.
* numChannels: Filled with the number of channels in the image.
*
* Returns a block of memory suitable for use with REFRESH_SetTextureData2D.
* Be sure to free the memory with REFRESH_Image_Free after use!
*/
REFRESHAPI uint8_t* REFRESH_Image_Load(
char const *filename,
int32_t *w,
int32_t *h,
int32_t *numChannels
);
/* Frees memory returned by REFRESH_Image_Load. (Do NOT free the memory yourself!)
*
* mem: A pointer previously returned by REFRESH_Image_Load.
*/
REFRESHAPI void REFRESH_Image_Free(uint8_t *mem);
/* Image Write API */
/* Encodes RGBA8 image data into PNG data.
*
* filename: The filename that the image will be written to.
* w: The width of the PNG data.
* h: The height of the PNG data.
* data: The raw RGBA8 image data.
*/
REFRESHAPI void REFRESH_Image_SavePNG(
char const *filename,
int32_t w,
int32_t h,
uint8_t *data
);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* REFRESH_IMAGE_H */
/* vim: set noexpandtab shiftwidth=8 tabstop=8: */

View File

@ -2896,11 +2896,26 @@ static SamplerDescriptorSetCache* VULKAN_INTERNAL_CreateSamplerDescriptorSetCach
VkDescriptorSetLayout descriptorSetLayout, VkDescriptorSetLayout descriptorSetLayout,
uint32_t samplerBindingCount uint32_t samplerBindingCount
) { ) {
SamplerDescriptorSetCache *samplerDescriptorSetCache = SDL_malloc(sizeof(samplerDescriptorSetCache)); uint32_t i;
SamplerDescriptorSetCache *samplerDescriptorSetCache = SDL_malloc(sizeof(SamplerDescriptorSetCache));
samplerDescriptorSetCache->elements = SDL_malloc(sizeof(SamplerDescriptorSetHashMap) * 16);
samplerDescriptorSetCache->count = 0;
samplerDescriptorSetCache->capacity = 16;
for (i = 0; i < NUM_DESCRIPTOR_SET_HASH_BUCKETS; i += 1)
{
samplerDescriptorSetCache->buckets[i].elements = NULL;
samplerDescriptorSetCache->buckets[i].count = 0;
samplerDescriptorSetCache->buckets[i].capacity = 0;
}
samplerDescriptorSetCache->descriptorSetLayout = descriptorSetLayout; samplerDescriptorSetCache->descriptorSetLayout = descriptorSetLayout;
samplerDescriptorSetCache->samplerBindingCount = samplerBindingCount; samplerDescriptorSetCache->samplerBindingCount = samplerBindingCount;
samplerDescriptorSetCache->samplerDescriptorPools = SDL_malloc(sizeof(VkDescriptorPool));
samplerDescriptorSetCache->samplerDescriptorPoolCount = 1;
VULKAN_INTERNAL_CreateSamplerDescriptorPool( VULKAN_INTERNAL_CreateSamplerDescriptorPool(
renderer, renderer,
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
@ -5057,7 +5072,7 @@ static void VULKAN_SetFragmentSamplers(
VulkanGraphicsPipeline *graphicsPipeline = (VulkanGraphicsPipeline*) pipeline; VulkanGraphicsPipeline *graphicsPipeline = (VulkanGraphicsPipeline*) pipeline;
SamplerDescriptorSetData fragmentSamplerDescriptorSetData; SamplerDescriptorSetData fragmentSamplerDescriptorSetData;
if (graphicsPipeline->pipelineLayout->vertexSamplerDescriptorSetCache == NULL) if (graphicsPipeline->pipelineLayout->fragmentSamplerDescriptorSetCache == NULL)
{ {
return; return;
} }
@ -5067,6 +5082,20 @@ static void VULKAN_SetFragmentSamplers(
for (i = 0; i < samplerCount; i += 1) for (i = 0; i < samplerCount; i += 1)
{ {
currentTexture = (VulkanTexture*) pTextures[i]; currentTexture = (VulkanTexture*) pTextures[i];
VULKAN_INTERNAL_ImageMemoryBarrier(
renderer,
RESOURCE_ACCESS_FRAGMENT_SHADER_READ_SAMPLED_IMAGE,
VK_IMAGE_ASPECT_COLOR_BIT,
0,
currentTexture->layerCount,
0,
currentTexture->levelCount,
0,
currentTexture->image,
&currentTexture->resourceAccessType
);
fragmentSamplerDescriptorSetData.descriptorImageInfo[i].imageView = currentTexture->view; fragmentSamplerDescriptorSetData.descriptorImageInfo[i].imageView = currentTexture->view;
fragmentSamplerDescriptorSetData.descriptorImageInfo[i].sampler = (VkSampler) pSamplers[i]; fragmentSamplerDescriptorSetData.descriptorImageInfo[i].sampler = (VkSampler) pSamplers[i];
fragmentSamplerDescriptorSetData.descriptorImageInfo[i].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; fragmentSamplerDescriptorSetData.descriptorImageInfo[i].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;

217
src/Refresh_Image.c Normal file
View File

@ -0,0 +1,217 @@
/* Refresh - XNA-inspired 3D Graphics Library with modern capabilities
*
* Copyright (c) 2020 Ethan Lee and Evan Hemsley
*
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from
* the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software in a
* product, an acknowledgment in the product documentation would be
* appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source distribution.
*
* Ethan "flibitijibibo" Lee <flibitijibibo@flibitijibibo.com>
* Evan "cosmonaut" Hemsley <evan@moonside.games>
*
* This source file is heavily borrowed from FNA3D_Image.h and was originally
* written by Ethan Lee.
*/
#include "Refresh_Image.h"
#include <SDL.h>
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
#pragma GCC diagnostic ignored "-Wunused-function"
#ifndef __clang__
#pragma GCC diagnostic ignored "-Wmisleading-indentation"
#endif
#ifndef __STDC_WANT_SECURE_LIB__
#define __STDC_WANT_SECURE_LIB__ 1
#endif
#define sprintf_s SDL_snprintf
#define abs SDL_abs
#define ceilf SDL_ceilf
#define floorf SDL_floorf
#define ldexp SDL_scalbn
#define pow SDL_pow
#define strtol SDL_strtol
#ifdef memcmp
#undef memcmp
#endif
#define memcmp SDL_memcmp
#ifdef memcpy
#undef memcpy
#endif
#define memcpy SDL_memcpy
#ifdef memmove
#undef memmove
#endif
#define memmove SDL_memmove
#ifdef memset
#undef memset
#endif
#define memset SDL_memset
#ifdef strcmp
#undef strcmp
#endif
#define strcmp SDL_strcmp
#ifdef strlen
#undef strlen
#endif
#define strlen SDL_strlen
#ifdef strncmp
#undef strncmp
#endif
#define strncmp SDL_strncmp
/* These are per the Texture2D.FromStream spec */
#define STBI_ONLY_PNG
/* These are per the Texture2D.SaveAs* spec */
#define STBIW_ONLY_PNG
#if !SDL_VERSION_ATLEAST(2, 0, 13)
static void *
SDL_SIMDRealloc(void *mem, const size_t len)
{
const size_t alignment = SDL_SIMDGetAlignment();
const size_t padding = alignment - (len % alignment);
const size_t padded = (padding != alignment) ? (len + padding) : len;
Uint8 *retval = (Uint8*) mem;
void *oldmem = mem;
size_t memdiff, ptrdiff;
Uint8 *ptr;
if (mem) {
void **realptr = (void **) mem;
realptr--;
mem = *(((void **) mem) - 1);
/* Check the delta between the real pointer and user pointer */
memdiff = ((size_t) oldmem) - ((size_t) mem);
}
ptr = (Uint8 *) SDL_realloc(mem, padded + alignment + sizeof (void *));
if (ptr == mem) {
return retval; /* Pointer didn't change, nothing to do */
}
if (ptr == NULL) {
return NULL; /* Out of memory, bail! */
}
/* Store the actual malloc pointer right before our aligned pointer. */
retval = ptr + sizeof (void *);
retval += alignment - (((size_t) retval) % alignment);
/* Make sure the delta is the same! */
if (mem) {
ptrdiff = ((size_t) retval) - ((size_t) ptr);
if (memdiff != ptrdiff) { /* Delta has changed, copy to new offset! */
oldmem = (void*) (((size_t) ptr) + memdiff);
/* Even though the data past the old `len` is undefined, this is the
* only length value we have, and it guarantees that we copy all the
* previous memory anyhow.
*/
SDL_memmove(retval, oldmem, len);
}
}
/* Actually store the malloc pointer, finally. */
*(((void **) retval) - 1) = ptr;
return retval;
}
#endif
#define STB_IMAGE_STATIC
#define STBI_ASSERT SDL_assert
#define STBI_MALLOC SDL_SIMDAlloc
#define STBI_REALLOC SDL_SIMDRealloc
#define STBI_FREE SDL_SIMDFree
#define STB_IMAGE_IMPLEMENTATION
#ifdef __MINGW32__
#define STBI_NO_THREAD_LOCALS /* FIXME: Port to SDL_TLS -flibit */
#endif
#include "stb_image.h"
#define MINIZ_NO_STDIO
#define MINIZ_NO_TIME
#define MINIZ_SDL_MALLOC
#define MZ_ASSERT(x) SDL_assert(x)
#include "miniz.h"
/* Thanks Daniel Gibson! */
static unsigned char* dgibson_stbi_zlib_compress(
unsigned char *data,
int data_len,
int *out_len,
int quality
) {
mz_ulong buflen = mz_compressBound(data_len);
unsigned char *buf = SDL_malloc(buflen);
if ( buf == NULL ||
mz_compress2(buf, &buflen, data, data_len, quality) != 0 )
{
SDL_free(buf);
return NULL;
}
*out_len = buflen;
return buf;
}
#define STB_IMAGE_WRITE_STATIC
#define STBIW_ASSERT SDL_assert
#define STBIW_MALLOC SDL_malloc
#define STBIW_REALLOC SDL_realloc
#define STBIW_FREE SDL_free
#define STBIW_ZLIB_COMPRESS dgibson_stbi_zlib_compress
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include "stb_image_write.h"
#pragma GCC diagnostic pop
/* Image Read API */
uint8_t* REFRESH_Image_Load(
char const *filename,
int32_t *w,
int32_t *h,
int32_t *numChannels
) {
return stbi_load(filename, w, h, numChannels, STBI_rgb_alpha);
}
void REFRESH_Image_Free(uint8_t *mem)
{
stbi_image_free(mem);
}
/* Image Write API */
void REFRESH_Image_SavePNG(
const char *filename,
int32_t w,
int32_t h,
uint8_t *data
) {
stbi_write_png(filename, w, h, 4, data, w * 4);
}
/* vim: set noexpandtab shiftwidth=8 tabstop=8: */

4942
src/miniz.h Normal file

File diff suppressed because it is too large Load Diff

7768
src/stb_image.h Normal file

File diff suppressed because it is too large Load Diff

1757
src/stb_image_write.h Normal file

File diff suppressed because it is too large Load Diff