mirror of https://github.com/bjornbytes/lovr.git
Sampler;
This commit is contained in:
parent
203a60c63a
commit
22e15513f9
|
@ -423,6 +423,7 @@ if(LOVR_ENABLE_GRAPHICS)
|
|||
src/api/l_graphics.c
|
||||
src/api/l_graphics_buffer.c
|
||||
src/api/l_graphics_texture.c
|
||||
src/api/l_graphics_sampler.c
|
||||
src/api/l_graphics_pass.c
|
||||
)
|
||||
|
||||
|
|
|
@ -15,6 +15,17 @@ StringEntry lovrBufferLayout[] = {
|
|||
{ 0 }
|
||||
};
|
||||
|
||||
StringEntry lovrCompareMode[] = {
|
||||
[COMPARE_NONE] = ENTRY("none"),
|
||||
[COMPARE_EQUAL] = ENTRY("equal"),
|
||||
[COMPARE_NEQUAL] = ENTRY("notequal"),
|
||||
[COMPARE_LESS] = ENTRY("less"),
|
||||
[COMPARE_LEQUAL] = ENTRY("lequal"),
|
||||
[COMPARE_GREATER] = ENTRY("greater"),
|
||||
[COMPARE_GEQUAL] = ENTRY("gequal"),
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
StringEntry lovrFieldType[] = {
|
||||
[FIELD_I8x4] = ENTRY("i8x4"),
|
||||
[FIELD_U8x4] = ENTRY("u8x4"),
|
||||
|
@ -51,6 +62,12 @@ StringEntry lovrFieldType[] = {
|
|||
{ 0 }
|
||||
};
|
||||
|
||||
StringEntry lovrFilterMode[] = {
|
||||
[FILTER_NEAREST] = ENTRY("nearest"),
|
||||
[FILTER_LINEAR] = ENTRY("linear"),
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
StringEntry lovrPassType[] = {
|
||||
[PASS_RENDER] = ENTRY("render"),
|
||||
[PASS_COMPUTE] = ENTRY("compute"),
|
||||
|
@ -86,6 +103,12 @@ StringEntry lovrTextureUsage[] = {
|
|||
{ 0 }
|
||||
};
|
||||
|
||||
StringEntry lovrWrapMode[] = {
|
||||
[WRAP_CLAMP] = ENTRY("clamp"),
|
||||
[WRAP_REPEAT] = ENTRY("repeat"),
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static struct { uint32_t size, scalarAlign, baseAlign, components; } fieldInfo[] = {
|
||||
[FIELD_I8x4] = { 4, 1, 4, 4 },
|
||||
[FIELD_U8x4] = { 4, 1, 4, 4 },
|
||||
|
@ -705,6 +728,74 @@ static int l_lovrGraphicsNewTexture(lua_State* L) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int l_lovrGraphicsNewSampler(lua_State* L) {
|
||||
SamplerInfo info = {
|
||||
.min = FILTER_LINEAR,
|
||||
.mag = FILTER_LINEAR,
|
||||
.mip = FILTER_LINEAR,
|
||||
.wrap = { WRAP_REPEAT, WRAP_REPEAT, WRAP_REPEAT },
|
||||
.range = { 0.f, -1.f }
|
||||
};
|
||||
|
||||
luaL_checktype(L, 1, LUA_TTABLE);
|
||||
|
||||
lua_getfield(L, 1, "filter");
|
||||
if (lua_isstring(L, -1)) {
|
||||
info.min = info.mag = info.mip = luax_checkenum(L, -1, FilterMode, NULL);
|
||||
} else if (lua_istable(L, -1)) {
|
||||
lua_rawgeti(L, -1, 1);
|
||||
lua_rawgeti(L, -2, 2);
|
||||
lua_rawgeti(L, -3, 3);
|
||||
info.min = luax_checkenum(L, -3, FilterMode, NULL);
|
||||
info.mag = luax_checkenum(L, -2, FilterMode, NULL);
|
||||
info.mip = luax_checkenum(L, -1, FilterMode, NULL);
|
||||
lua_pop(L, 3);
|
||||
} else if (!lua_isnil(L, -1)) {
|
||||
lovrThrow("Expected string or table for Sampler filter");
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_getfield(L, 1, "wrap");
|
||||
if (lua_isstring(L, -1)) {
|
||||
info.wrap[0] = info.wrap[1] = info.wrap[2] = luax_checkenum(L, -1, WrapMode, NULL);
|
||||
} else if (lua_istable(L, -1)) {
|
||||
lua_rawgeti(L, -1, 1);
|
||||
lua_rawgeti(L, -2, 2);
|
||||
lua_rawgeti(L, -3, 3);
|
||||
info.wrap[0] = luax_checkenum(L, -3, WrapMode, NULL);
|
||||
info.wrap[1] = luax_checkenum(L, -2, WrapMode, NULL);
|
||||
info.wrap[2] = luax_checkenum(L, -1, WrapMode, NULL);
|
||||
lua_pop(L, 3);
|
||||
} else if (!lua_isnil(L, -1)) {
|
||||
lovrThrow("Expected string or table for Sampler wrap");
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_getfield(L, 1, "compare");
|
||||
info.compare = luax_checkenum(L, -1, CompareMode, "none");
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_getfield(L, 1, "anisotropy");
|
||||
info.anisotropy = luax_optfloat(L, -1, 0.f);
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_getfield(L, 1, "mipmaprange");
|
||||
if (!lua_isnil(L, -1)) {
|
||||
lovrAssert(lua_istable(L, -1), "Sampler mipmap range must be nil or a table");
|
||||
lua_rawgeti(L, -1, 1);
|
||||
lua_rawgeti(L, -2, 2);
|
||||
info.range[0] = luax_checkfloat(L, -2);
|
||||
info.range[1] = luax_checkfloat(L, -1);
|
||||
lua_pop(L, 2);
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
|
||||
Sampler* sampler = lovrSamplerCreate(&info);
|
||||
luax_pushtype(L, Sampler, sampler);
|
||||
lovrRelease(sampler, lovrSamplerDestroy);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const luaL_Reg lovrGraphics[] = {
|
||||
{ "init", l_lovrGraphicsInit },
|
||||
{ "submit", l_lovrGraphicsSubmit },
|
||||
|
@ -716,6 +807,7 @@ static const luaL_Reg lovrGraphics[] = {
|
|||
{ "buffer", l_lovrGraphicsBuffer },
|
||||
{ "newBuffer", l_lovrGraphicsNewBuffer },
|
||||
{ "newTexture", l_lovrGraphicsNewTexture },
|
||||
{ "newSampler", l_lovrGraphicsNewSampler },
|
||||
{ "pass", l_lovrGraphicsPass },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
|
|
@ -4,10 +4,12 @@
|
|||
|
||||
typedef struct gpu_buffer gpu_buffer;
|
||||
typedef struct gpu_texture gpu_texture;
|
||||
typedef struct gpu_sampler gpu_sampler;
|
||||
typedef struct gpu_stream gpu_stream;
|
||||
|
||||
size_t gpu_sizeof_buffer(void);
|
||||
size_t gpu_sizeof_texture(void);
|
||||
size_t gpu_sizeof_sampler(void);
|
||||
|
||||
// Buffer
|
||||
|
||||
|
@ -132,6 +134,35 @@ typedef enum {
|
|||
GPU_FILTER_LINEAR
|
||||
} gpu_filter;
|
||||
|
||||
typedef enum {
|
||||
GPU_WRAP_CLAMP,
|
||||
GPU_WRAP_REPEAT,
|
||||
GPU_WRAP_MIRROR
|
||||
} gpu_wrap;
|
||||
|
||||
typedef enum {
|
||||
GPU_COMPARE_NONE,
|
||||
GPU_COMPARE_EQUAL,
|
||||
GPU_COMPARE_NEQUAL,
|
||||
GPU_COMPARE_LESS,
|
||||
GPU_COMPARE_LEQUAL,
|
||||
GPU_COMPARE_GREATER,
|
||||
GPU_COMPARE_GEQUAL
|
||||
} gpu_compare_mode;
|
||||
|
||||
typedef struct {
|
||||
gpu_filter min;
|
||||
gpu_filter mag;
|
||||
gpu_filter mip;
|
||||
gpu_wrap wrap[3];
|
||||
gpu_compare_mode compare;
|
||||
float anisotropy;
|
||||
float lodClamp[2];
|
||||
} gpu_sampler_info;
|
||||
|
||||
bool gpu_sampler_init(gpu_sampler* sampler, gpu_sampler_info* info);
|
||||
void gpu_sampler_destroy(gpu_sampler* sampler);
|
||||
|
||||
// Stream
|
||||
|
||||
gpu_stream* gpu_stream_begin(const char* label);
|
||||
|
|
|
@ -27,12 +27,17 @@ struct gpu_texture {
|
|||
bool layered;
|
||||
};
|
||||
|
||||
struct gpu_sampler {
|
||||
VkSampler handle;
|
||||
};
|
||||
|
||||
struct gpu_stream {
|
||||
VkCommandBuffer commands;
|
||||
};
|
||||
|
||||
size_t gpu_sizeof_buffer() { return sizeof(gpu_buffer); }
|
||||
size_t gpu_sizeof_texture() { return sizeof(gpu_texture); }
|
||||
size_t gpu_sizeof_sampler() { return sizeof(gpu_sampler); }
|
||||
|
||||
// Internals
|
||||
|
||||
|
@ -617,6 +622,62 @@ void gpu_texture_destroy(gpu_texture* texture) {
|
|||
gpu_release(state.memory + texture->memory);
|
||||
}
|
||||
|
||||
// Sampler
|
||||
|
||||
bool gpu_sampler_init(gpu_sampler* sampler, gpu_sampler_info* info) {
|
||||
static const VkFilter filters[] = {
|
||||
[GPU_FILTER_NEAREST] = VK_FILTER_NEAREST,
|
||||
[GPU_FILTER_LINEAR] = VK_FILTER_LINEAR
|
||||
};
|
||||
|
||||
static const VkSamplerMipmapMode mipFilters[] = {
|
||||
[GPU_FILTER_NEAREST] = VK_SAMPLER_MIPMAP_MODE_NEAREST,
|
||||
[GPU_FILTER_LINEAR] = VK_SAMPLER_MIPMAP_MODE_LINEAR
|
||||
};
|
||||
|
||||
static const VkSamplerAddressMode wraps[] = {
|
||||
[GPU_WRAP_CLAMP] = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
|
||||
[GPU_WRAP_REPEAT] = VK_SAMPLER_ADDRESS_MODE_REPEAT,
|
||||
[GPU_WRAP_MIRROR] = VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT
|
||||
};
|
||||
|
||||
static const VkCompareOp compareOps[] = {
|
||||
[GPU_COMPARE_NONE] = VK_COMPARE_OP_ALWAYS,
|
||||
[GPU_COMPARE_EQUAL] = VK_COMPARE_OP_EQUAL,
|
||||
[GPU_COMPARE_NEQUAL] = VK_COMPARE_OP_NOT_EQUAL,
|
||||
[GPU_COMPARE_LESS] = VK_COMPARE_OP_LESS,
|
||||
[GPU_COMPARE_LEQUAL] = VK_COMPARE_OP_LESS_OR_EQUAL,
|
||||
[GPU_COMPARE_GREATER] = VK_COMPARE_OP_GREATER,
|
||||
[GPU_COMPARE_GEQUAL] = VK_COMPARE_OP_GREATER_OR_EQUAL
|
||||
};
|
||||
|
||||
VkSamplerCreateInfo samplerInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
|
||||
.magFilter = filters[info->mag],
|
||||
.minFilter = filters[info->min],
|
||||
.mipmapMode = mipFilters[info->mip],
|
||||
.addressModeU = wraps[info->wrap[0]],
|
||||
.addressModeV = wraps[info->wrap[1]],
|
||||
.addressModeW = wraps[info->wrap[2]],
|
||||
.anisotropyEnable = info->anisotropy >= 1.f,
|
||||
.maxAnisotropy = info->anisotropy,
|
||||
.compareEnable = info->compare != GPU_COMPARE_NONE,
|
||||
.compareOp = compareOps[info->compare],
|
||||
.minLod = info->lodClamp[0],
|
||||
.maxLod = info->lodClamp[1] < 0.f ? VK_LOD_CLAMP_NONE : info->lodClamp[1]
|
||||
};
|
||||
|
||||
VK(vkCreateSampler(state.device, &samplerInfo, NULL, &sampler->handle), "Could not create sampler") {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void gpu_sampler_destroy(gpu_sampler* sampler) {
|
||||
condemn(sampler->handle, VK_OBJECT_TYPE_SAMPLER);
|
||||
}
|
||||
|
||||
// Stream
|
||||
|
||||
gpu_stream* gpu_stream_begin(const char* label) {
|
||||
|
|
|
@ -24,6 +24,12 @@ struct Texture {
|
|||
TextureInfo info;
|
||||
};
|
||||
|
||||
struct Sampler {
|
||||
uint32_t ref;
|
||||
gpu_sampler* gpu;
|
||||
SamplerInfo info;
|
||||
};
|
||||
|
||||
struct Pass {
|
||||
uint32_t ref;
|
||||
PassInfo info;
|
||||
|
@ -460,6 +466,44 @@ const TextureInfo* lovrTextureGetInfo(Texture* texture) {
|
|||
return &texture->info;
|
||||
}
|
||||
|
||||
// Sampler
|
||||
|
||||
Sampler* lovrSamplerCreate(SamplerInfo* info) {
|
||||
lovrCheck(info->range[1] < 0.f || info->range[1] >= info->range[0], "Invalid Sampler mipmap range");
|
||||
lovrCheck(info->anisotropy <= state.limits.anisotropy, "Sampler anisotropy (%f) exceeds anisotropy limit (%f)", info->anisotropy, state.limits.anisotropy);
|
||||
|
||||
Sampler* sampler = calloc(1, sizeof(Sampler) + gpu_sizeof_sampler());
|
||||
lovrAssert(sampler, "Out of memory");
|
||||
sampler->gpu = (gpu_sampler*) (sampler + 1);
|
||||
sampler->info = *info;
|
||||
sampler->ref = 1;
|
||||
|
||||
gpu_sampler_info gpu = {
|
||||
.min = (gpu_filter) info->min,
|
||||
.mag = (gpu_filter) info->mag,
|
||||
.mip = (gpu_filter) info->mip,
|
||||
.wrap[0] = (gpu_wrap) info->wrap[0],
|
||||
.wrap[1] = (gpu_wrap) info->wrap[1],
|
||||
.wrap[2] = (gpu_wrap) info->wrap[2],
|
||||
.compare = (gpu_compare_mode) info->compare,
|
||||
.anisotropy = MIN(info->anisotropy, state.limits.anisotropy),
|
||||
.lodClamp = { info->range[0], info->range[1] }
|
||||
};
|
||||
|
||||
lovrAssert(gpu_sampler_init(sampler->gpu, &gpu), "Failed to initialize sampler");
|
||||
return sampler;
|
||||
}
|
||||
|
||||
void lovrSamplerDestroy(void* ref) {
|
||||
Sampler* sampler = ref;
|
||||
gpu_sampler_destroy(sampler->gpu);
|
||||
free(sampler);
|
||||
}
|
||||
|
||||
const SamplerInfo* lovrSamplerGetInfo(Sampler* sampler) {
|
||||
return &sampler->info;
|
||||
}
|
||||
|
||||
// Pass
|
||||
|
||||
Pass* lovrGraphicsGetPass(PassInfo* info) {
|
||||
|
|
|
@ -7,6 +7,7 @@ struct Image;
|
|||
|
||||
typedef struct Buffer Buffer;
|
||||
typedef struct Texture Texture;
|
||||
typedef struct Sampler Sampler;
|
||||
typedef struct Pass Pass;
|
||||
|
||||
typedef struct {
|
||||
|
@ -192,6 +193,41 @@ Texture* lovrTextureCreateView(TextureViewInfo* view);
|
|||
void lovrTextureDestroy(void* ref);
|
||||
const TextureInfo* lovrTextureGetInfo(Texture* texture);
|
||||
|
||||
// Sampler
|
||||
|
||||
typedef enum {
|
||||
FILTER_NEAREST,
|
||||
FILTER_LINEAR
|
||||
} FilterMode;
|
||||
|
||||
typedef enum {
|
||||
WRAP_CLAMP,
|
||||
WRAP_REPEAT,
|
||||
WRAP_MIRROR
|
||||
} WrapMode;
|
||||
|
||||
typedef enum {
|
||||
COMPARE_NONE,
|
||||
COMPARE_EQUAL,
|
||||
COMPARE_NEQUAL,
|
||||
COMPARE_LESS,
|
||||
COMPARE_LEQUAL,
|
||||
COMPARE_GREATER,
|
||||
COMPARE_GEQUAL
|
||||
} CompareMode;
|
||||
|
||||
typedef struct {
|
||||
FilterMode min, mag, mip;
|
||||
WrapMode wrap[3];
|
||||
CompareMode compare;
|
||||
float anisotropy;
|
||||
float range[2];
|
||||
} SamplerInfo;
|
||||
|
||||
Sampler* lovrSamplerCreate(SamplerInfo* info);
|
||||
void lovrSamplerDestroy(void* ref);
|
||||
const SamplerInfo* lovrSamplerGetInfo(Sampler* sampler);
|
||||
|
||||
// Pass
|
||||
|
||||
typedef enum {
|
||||
|
|
Loading…
Reference in New Issue