Texture addressing mode selection (repeat or clamp).
This commit is contained in:
parent
327ebe2daf
commit
4d33fcf925
|
|
@ -750,7 +750,7 @@ void RE_UploadCinematic (int w, int h, int cols, int rows, const byte *data, int
|
||||||
vkDestroyImage(vk.device, image.handle, nullptr);
|
vkDestroyImage(vk.device, image.handle, nullptr);
|
||||||
vkDestroyImageView(vk.device, image.view, nullptr);
|
vkDestroyImageView(vk.device, image.view, nullptr);
|
||||||
vkFreeDescriptorSets(vk.device, vk.descriptor_pool, 1, &image.descriptor_set);
|
vkFreeDescriptorSets(vk.device, vk.descriptor_pool, 1, &image.descriptor_set);
|
||||||
image = vk_create_image(cols, rows, 1);
|
image = vk_create_image(cols, rows, 1, false);
|
||||||
vk_upload_image_data(image.handle, cols, rows, false, data);
|
vk_upload_image_data(image.handle, cols, rows, false, data);
|
||||||
} else {
|
} else {
|
||||||
if (dirty) {
|
if (dirty) {
|
||||||
|
|
|
||||||
|
|
@ -507,15 +507,17 @@ Upload32
|
||||||
|
|
||||||
===============
|
===============
|
||||||
*/
|
*/
|
||||||
extern qboolean charSet;
|
|
||||||
static void Upload32( unsigned *data,
|
static void Upload32( unsigned *data,
|
||||||
int width, int height,
|
int width, int height,
|
||||||
qboolean mipmap,
|
qboolean mipmap,
|
||||||
qboolean picmip,
|
qboolean picmip,
|
||||||
qboolean lightMap,
|
qboolean lightMap,
|
||||||
Vk_Image& image,
|
|
||||||
int *format,
|
int *format,
|
||||||
int *pUploadWidth, int *pUploadHeight )
|
int *pUploadWidth, int *pUploadHeight,
|
||||||
|
// VULKAN
|
||||||
|
Vk_Image& image,
|
||||||
|
bool repeat_texture
|
||||||
|
)
|
||||||
{
|
{
|
||||||
int samples;
|
int samples;
|
||||||
unsigned *scaledBuffer = NULL;
|
unsigned *scaledBuffer = NULL;
|
||||||
|
|
@ -709,7 +711,7 @@ static void Upload32( unsigned *data,
|
||||||
done:
|
done:
|
||||||
|
|
||||||
// VULKAN
|
// VULKAN
|
||||||
image = vk_create_image(*pUploadWidth, *pUploadHeight, miplevel + 1);
|
image = vk_create_image(*pUploadWidth, *pUploadHeight, miplevel + 1, repeat_texture);
|
||||||
vk_upload_image_data(image.handle, *pUploadWidth, *pUploadHeight, mipmap == qtrue, mipmap_buffer);
|
vk_upload_image_data(image.handle, *pUploadWidth, *pUploadHeight, mipmap == qtrue, mipmap_buffer);
|
||||||
|
|
||||||
if (mipmap_buffer != nullptr)
|
if (mipmap_buffer != nullptr)
|
||||||
|
|
@ -780,10 +782,12 @@ image_t *R_CreateImage( const char *name, const byte *pic, int width, int height
|
||||||
image->mipmap,
|
image->mipmap,
|
||||||
allowPicmip,
|
allowPicmip,
|
||||||
isLightmap,
|
isLightmap,
|
||||||
vk_resources.images[image->index],
|
|
||||||
&image->internalFormat,
|
&image->internalFormat,
|
||||||
&image->uploadWidth,
|
&image->uploadWidth,
|
||||||
&image->uploadHeight );
|
&image->uploadHeight,
|
||||||
|
vk_resources.images[image->index],
|
||||||
|
glWrapClampMode == GL_REPEAT
|
||||||
|
);
|
||||||
|
|
||||||
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, glWrapClampMode );
|
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, glWrapClampMode );
|
||||||
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, glWrapClampMode );
|
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, glWrapClampMode );
|
||||||
|
|
@ -1367,7 +1371,7 @@ static void LoadTGA ( const char *name, byte **pic, int *width, int *height)
|
||||||
ri.FS_FreeFile (buffer);
|
ri.FS_FreeFile (buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void LoadJPG( const char *filename, unsigned char **pic, int *width, int *height ) {
|
static void LoadJPG( const char *filename, byte **pic, int *width, int *height ) {
|
||||||
byte* fbuffer;
|
byte* fbuffer;
|
||||||
int len = ri.FS_ReadFile ( ( char * ) filename, (void **)&fbuffer);
|
int len = ri.FS_ReadFile ( ( char * ) filename, (void **)&fbuffer);
|
||||||
if (!fbuffer) {
|
if (!fbuffer) {
|
||||||
|
|
|
||||||
|
|
@ -2161,24 +2161,24 @@ static shader_t *FinishShader( void ) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// VULKAN
|
// VULKAN
|
||||||
Vk_Pipeline_Desc desc;
|
Vk_Pipeline_Def def;
|
||||||
desc.face_culling = shader.cullType;
|
def.face_culling = shader.cullType;
|
||||||
desc.polygon_offset = (shader.polygonOffset == qtrue);
|
def.polygon_offset = (shader.polygonOffset == qtrue);
|
||||||
|
|
||||||
for (int i = 0; i < stage; i++) {
|
for (int i = 0; i < stage; i++) {
|
||||||
shaderStage_t *pStage = &stages[i];
|
shaderStage_t *pStage = &stages[i];
|
||||||
desc.state_bits = pStage->stateBits;
|
def.state_bits = pStage->stateBits;
|
||||||
|
|
||||||
if (pStage->bundle[1].image[0] == nullptr)
|
if (pStage->bundle[1].image[0] == nullptr)
|
||||||
desc.shader_type = Vk_Shader_Type::single_texture;
|
def.shader_type = Vk_Shader_Type::single_texture;
|
||||||
else if (shader.multitextureEnv == GL_MODULATE)
|
else if (shader.multitextureEnv == GL_MODULATE)
|
||||||
desc.shader_type = Vk_Shader_Type::multi_texture_mul;
|
def.shader_type = Vk_Shader_Type::multi_texture_mul;
|
||||||
else if (shader.multitextureEnv == GL_ADD)
|
else if (shader.multitextureEnv == GL_ADD)
|
||||||
desc.shader_type = Vk_Shader_Type::multi_texture_add;
|
def.shader_type = Vk_Shader_Type::multi_texture_add;
|
||||||
else
|
else
|
||||||
ri.Error(ERR_DROP, "ERROR: could not determine vulkan shader type for shader '%s'\n", shader.name);
|
ri.Error(ERR_DROP, "ERROR: could not determine vulkan shader type for shader '%s'\n", shader.name);
|
||||||
|
|
||||||
pStage->vk_pipeline = vk_find_pipeline(desc);
|
pStage->vk_pipeline = vk_find_pipeline(def);
|
||||||
}
|
}
|
||||||
|
|
||||||
return GeneratePermanentShader();
|
return GeneratePermanentShader();
|
||||||
|
|
|
||||||
|
|
@ -509,7 +509,7 @@ static void ensure_staging_buffer_allocation(VkDeviceSize size) {
|
||||||
vk_resources.staging_buffer_ptr = (byte*)data;
|
vk_resources.staging_buffer_ptr = (byte*)data;
|
||||||
}
|
}
|
||||||
|
|
||||||
VkPipeline create_pipeline(const Vk_Pipeline_Desc&);
|
VkPipeline create_pipeline(const Vk_Pipeline_Def&);
|
||||||
|
|
||||||
void vk_create_instance(HWND hwnd) {
|
void vk_create_instance(HWND hwnd) {
|
||||||
vk_log_file = fopen("vk_dev.log", "w");
|
vk_log_file = fopen("vk_dev.log", "w");
|
||||||
|
|
@ -845,44 +845,17 @@ void vk_create_instance(HWND hwnd) {
|
||||||
vk.multi_texture_add_fs = create_shader_module(multi_texture_add_frag_spv, multi_texture_add_frag_spv_size);
|
vk.multi_texture_add_fs = create_shader_module(multi_texture_add_frag_spv, multi_texture_add_frag_spv_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// Samplers.
|
|
||||||
//
|
|
||||||
{
|
|
||||||
VkSamplerCreateInfo desc;
|
|
||||||
desc.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
|
|
||||||
desc.pNext = nullptr;
|
|
||||||
desc.flags = 0;
|
|
||||||
desc.magFilter = VK_FILTER_LINEAR;
|
|
||||||
desc.minFilter = VK_FILTER_LINEAR;
|
|
||||||
desc.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST;
|
|
||||||
desc.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT;
|
|
||||||
desc.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT;
|
|
||||||
desc.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT;
|
|
||||||
desc.mipLodBias = 0.0f;
|
|
||||||
desc.anisotropyEnable = VK_TRUE;
|
|
||||||
desc.maxAnisotropy = 1;
|
|
||||||
desc.compareEnable = VK_FALSE;
|
|
||||||
desc.compareOp = VK_COMPARE_OP_ALWAYS;
|
|
||||||
desc.minLod = 0.0f;
|
|
||||||
desc.maxLod = 12.0f;
|
|
||||||
desc.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK;
|
|
||||||
desc.unnormalizedCoordinates = VK_FALSE;
|
|
||||||
|
|
||||||
VK_CHECK(vkCreateSampler(vk.device, &desc, nullptr, &vk.sampler));
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Skybox pipeline.
|
// Skybox pipeline.
|
||||||
//
|
//
|
||||||
{
|
{
|
||||||
Vk_Pipeline_Desc desc;
|
Vk_Pipeline_Def def;
|
||||||
desc.shader_type = Vk_Shader_Type::single_texture;
|
def.shader_type = Vk_Shader_Type::single_texture;
|
||||||
desc.state_bits = 0;
|
def.state_bits = 0;
|
||||||
desc.face_culling = CT_FRONT_SIDED;
|
def.face_culling = CT_FRONT_SIDED;
|
||||||
desc.polygon_offset = false;
|
def.polygon_offset = false;
|
||||||
|
|
||||||
vk.skybox_pipeline = create_pipeline(desc);
|
vk.skybox_pipeline = create_pipeline(def);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -920,7 +893,6 @@ void vk_destroy_instance() {
|
||||||
vkDestroyShaderModule(vk.device, vk.multi_texture_mul_fs, nullptr);
|
vkDestroyShaderModule(vk.device, vk.multi_texture_mul_fs, nullptr);
|
||||||
vkDestroyShaderModule(vk.device, vk.multi_texture_add_fs, nullptr);
|
vkDestroyShaderModule(vk.device, vk.multi_texture_add_fs, nullptr);
|
||||||
|
|
||||||
vkDestroySampler(vk.device, vk.sampler, nullptr);
|
|
||||||
vkDestroyPipeline(vk.device, vk.skybox_pipeline, nullptr);
|
vkDestroyPipeline(vk.device, vk.skybox_pipeline, nullptr);
|
||||||
|
|
||||||
vkDestroySwapchainKHR(vk.device, vk.swapchain, nullptr);
|
vkDestroySwapchainKHR(vk.device, vk.swapchain, nullptr);
|
||||||
|
|
@ -946,6 +918,9 @@ void vk_destroy_resources() {
|
||||||
if (res.staging_buffer_memory != VK_NULL_HANDLE)
|
if (res.staging_buffer_memory != VK_NULL_HANDLE)
|
||||||
vkFreeMemory(vk.device, res.staging_buffer_memory, nullptr);
|
vkFreeMemory(vk.device, res.staging_buffer_memory, nullptr);
|
||||||
|
|
||||||
|
for (int i = 0; i < res.num_samplers; i++)
|
||||||
|
vkDestroySampler(vk.device, res.samplers[i], nullptr);
|
||||||
|
|
||||||
for (int i = 0; i < res.num_pipelines; i++)
|
for (int i = 0; i < res.num_pipelines; i++)
|
||||||
vkDestroyPipeline(vk.device, res.pipelines[i], nullptr);
|
vkDestroyPipeline(vk.device, res.pipelines[i], nullptr);
|
||||||
|
|
||||||
|
|
@ -988,7 +963,7 @@ static void record_buffer_memory_barrier(VkCommandBuffer cb, VkBuffer buffer,
|
||||||
vkCmdPipelineBarrier(cb, src_stages, dst_stages, 0, 0, nullptr, 1, &barrier, 0, nullptr);
|
vkCmdPipelineBarrier(cb, src_stages, dst_stages, 0, 0, nullptr, 1, &barrier, 0, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
Vk_Image vk_create_image(int width, int height, int mip_levels) {
|
Vk_Image vk_create_image(int width, int height, int mip_levels, bool repeat_texture) {
|
||||||
Vk_Image image;
|
Vk_Image image;
|
||||||
|
|
||||||
// create image
|
// create image
|
||||||
|
|
@ -1048,8 +1023,11 @@ Vk_Image vk_create_image(int width, int height, int mip_levels) {
|
||||||
|
|
||||||
VK_CHECK(vkAllocateDescriptorSets(vk.device, &desc, &image.descriptor_set));
|
VK_CHECK(vkAllocateDescriptorSets(vk.device, &desc, &image.descriptor_set));
|
||||||
|
|
||||||
|
Vk_Sampler_Def sampler_def;
|
||||||
|
sampler_def.repeat_texture = repeat_texture;
|
||||||
|
|
||||||
VkDescriptorImageInfo image_info;
|
VkDescriptorImageInfo image_info;
|
||||||
image_info.sampler = vk.sampler;
|
image_info.sampler = vk_find_sampler(sampler_def);
|
||||||
image_info.imageView = image.view;
|
image_info.imageView = image.view;
|
||||||
image_info.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
image_info.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||||
|
|
||||||
|
|
@ -1124,7 +1102,7 @@ void vk_upload_image_data(VkImage image, int width, int height, bool mipmap, con
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
static VkPipeline create_pipeline(const Vk_Pipeline_Desc& desc) {
|
static VkPipeline create_pipeline(const Vk_Pipeline_Def& def) {
|
||||||
auto get_shader_stage_desc = [](VkShaderStageFlagBits stage, VkShaderModule shader_module, const char* entry) {
|
auto get_shader_stage_desc = [](VkShaderStageFlagBits stage, VkShaderModule shader_module, const char* entry) {
|
||||||
VkPipelineShaderStageCreateInfo desc;
|
VkPipelineShaderStageCreateInfo desc;
|
||||||
desc.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
|
desc.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
|
||||||
|
|
@ -1141,13 +1119,13 @@ static VkPipeline create_pipeline(const Vk_Pipeline_Desc& desc) {
|
||||||
int32_t alpha_test_func;
|
int32_t alpha_test_func;
|
||||||
} specialization_data;
|
} specialization_data;
|
||||||
|
|
||||||
if ((desc.state_bits & GLS_ATEST_BITS) == 0)
|
if ((def.state_bits & GLS_ATEST_BITS) == 0)
|
||||||
specialization_data.alpha_test_func = 0;
|
specialization_data.alpha_test_func = 0;
|
||||||
else if (desc.state_bits & GLS_ATEST_GT_0)
|
else if (def.state_bits & GLS_ATEST_GT_0)
|
||||||
specialization_data.alpha_test_func = 1;
|
specialization_data.alpha_test_func = 1;
|
||||||
else if (desc.state_bits & GLS_ATEST_LT_80)
|
else if (def.state_bits & GLS_ATEST_LT_80)
|
||||||
specialization_data.alpha_test_func = 2;
|
specialization_data.alpha_test_func = 2;
|
||||||
else if (desc.state_bits & GLS_ATEST_GE_80)
|
else if (def.state_bits & GLS_ATEST_GE_80)
|
||||||
specialization_data.alpha_test_func = 3;
|
specialization_data.alpha_test_func = 3;
|
||||||
else
|
else
|
||||||
ri.Error(ERR_DROP, "create_pipeline: invalid alpha test state bits\n");
|
ri.Error(ERR_DROP, "create_pipeline: invalid alpha test state bits\n");
|
||||||
|
|
@ -1166,20 +1144,20 @@ static VkPipeline create_pipeline(const Vk_Pipeline_Desc& desc) {
|
||||||
std::vector<VkPipelineShaderStageCreateInfo> shader_stages_state;
|
std::vector<VkPipelineShaderStageCreateInfo> shader_stages_state;
|
||||||
|
|
||||||
VkShaderModule* vs_module, *fs_module;
|
VkShaderModule* vs_module, *fs_module;
|
||||||
if (desc.shader_type == Vk_Shader_Type::single_texture) {
|
if (def.shader_type == Vk_Shader_Type::single_texture) {
|
||||||
vs_module = &vk.single_texture_vs;
|
vs_module = &vk.single_texture_vs;
|
||||||
fs_module = &vk.single_texture_fs;
|
fs_module = &vk.single_texture_fs;
|
||||||
} else if (desc.shader_type == Vk_Shader_Type::multi_texture_mul) {
|
} else if (def.shader_type == Vk_Shader_Type::multi_texture_mul) {
|
||||||
vs_module = &vk.multi_texture_vs;
|
vs_module = &vk.multi_texture_vs;
|
||||||
fs_module = &vk.multi_texture_mul_fs;
|
fs_module = &vk.multi_texture_mul_fs;
|
||||||
} else if (desc.shader_type == Vk_Shader_Type::multi_texture_add) {
|
} else if (def.shader_type == Vk_Shader_Type::multi_texture_add) {
|
||||||
vs_module = &vk.multi_texture_vs;
|
vs_module = &vk.multi_texture_vs;
|
||||||
fs_module = &vk.multi_texture_add_fs;
|
fs_module = &vk.multi_texture_add_fs;
|
||||||
}
|
}
|
||||||
shader_stages_state.push_back(get_shader_stage_desc(VK_SHADER_STAGE_VERTEX_BIT, *vs_module, "main"));
|
shader_stages_state.push_back(get_shader_stage_desc(VK_SHADER_STAGE_VERTEX_BIT, *vs_module, "main"));
|
||||||
shader_stages_state.push_back(get_shader_stage_desc(VK_SHADER_STAGE_FRAGMENT_BIT, *fs_module, "main"));
|
shader_stages_state.push_back(get_shader_stage_desc(VK_SHADER_STAGE_FRAGMENT_BIT, *fs_module, "main"));
|
||||||
|
|
||||||
if (desc.state_bits & GLS_ATEST_BITS)
|
if (def.state_bits & GLS_ATEST_BITS)
|
||||||
shader_stages_state.back().pSpecializationInfo = &specialization_info;
|
shader_stages_state.back().pSpecializationInfo = &specialization_info;
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
@ -1235,9 +1213,9 @@ static VkPipeline create_pipeline(const Vk_Pipeline_Desc& desc) {
|
||||||
vertex_input_state.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
|
vertex_input_state.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
|
||||||
vertex_input_state.pNext = nullptr;
|
vertex_input_state.pNext = nullptr;
|
||||||
vertex_input_state.flags = 0;
|
vertex_input_state.flags = 0;
|
||||||
vertex_input_state.vertexBindingDescriptionCount = (desc.shader_type == Vk_Shader_Type::single_texture) ? 3 : 4;
|
vertex_input_state.vertexBindingDescriptionCount = (def.shader_type == Vk_Shader_Type::single_texture) ? 3 : 4;
|
||||||
vertex_input_state.pVertexBindingDescriptions = bindings;
|
vertex_input_state.pVertexBindingDescriptions = bindings;
|
||||||
vertex_input_state.vertexAttributeDescriptionCount = (desc.shader_type == Vk_Shader_Type::single_texture) ? 3 : 4;
|
vertex_input_state.vertexAttributeDescriptionCount = (def.shader_type == Vk_Shader_Type::single_texture) ? 3 : 4;
|
||||||
vertex_input_state.pVertexAttributeDescriptions = attribs;
|
vertex_input_state.pVertexAttributeDescriptions = attribs;
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
@ -1271,20 +1249,20 @@ static VkPipeline create_pipeline(const Vk_Pipeline_Desc& desc) {
|
||||||
rasterization_state.flags = 0;
|
rasterization_state.flags = 0;
|
||||||
rasterization_state.depthClampEnable = VK_FALSE;
|
rasterization_state.depthClampEnable = VK_FALSE;
|
||||||
rasterization_state.rasterizerDiscardEnable = VK_FALSE;
|
rasterization_state.rasterizerDiscardEnable = VK_FALSE;
|
||||||
rasterization_state.polygonMode = (desc.state_bits & GLS_POLYMODE_LINE) ? VK_POLYGON_MODE_LINE : VK_POLYGON_MODE_FILL;
|
rasterization_state.polygonMode = (def.state_bits & GLS_POLYMODE_LINE) ? VK_POLYGON_MODE_LINE : VK_POLYGON_MODE_FILL;
|
||||||
|
|
||||||
if (desc.face_culling == CT_TWO_SIDED)
|
if (def.face_culling == CT_TWO_SIDED)
|
||||||
rasterization_state.cullMode = VK_CULL_MODE_NONE;
|
rasterization_state.cullMode = VK_CULL_MODE_NONE;
|
||||||
else if (desc.face_culling == CT_FRONT_SIDED)
|
else if (def.face_culling == CT_FRONT_SIDED)
|
||||||
rasterization_state.cullMode = VK_CULL_MODE_BACK_BIT;
|
rasterization_state.cullMode = VK_CULL_MODE_BACK_BIT;
|
||||||
else if (desc.face_culling == CT_BACK_SIDED)
|
else if (def.face_culling == CT_BACK_SIDED)
|
||||||
rasterization_state.cullMode = VK_CULL_MODE_FRONT_BIT;
|
rasterization_state.cullMode = VK_CULL_MODE_FRONT_BIT;
|
||||||
else
|
else
|
||||||
ri.Error(ERR_DROP, "create_pipeline: invalid face culling mode\n");
|
ri.Error(ERR_DROP, "create_pipeline: invalid face culling mode\n");
|
||||||
|
|
||||||
rasterization_state.frontFace = VK_FRONT_FACE_CLOCKWISE; // Q3 defaults to clockwise vertex order
|
rasterization_state.frontFace = VK_FRONT_FACE_CLOCKWISE; // Q3 defaults to clockwise vertex order
|
||||||
|
|
||||||
rasterization_state.depthBiasEnable = desc.polygon_offset ? VK_TRUE : VK_FALSE;
|
rasterization_state.depthBiasEnable = def.polygon_offset ? VK_TRUE : VK_FALSE;
|
||||||
rasterization_state.depthBiasConstantFactor = 0.0f; // dynamic depth bias state
|
rasterization_state.depthBiasConstantFactor = 0.0f; // dynamic depth bias state
|
||||||
rasterization_state.depthBiasClamp = 0.0f; // dynamic depth bias state
|
rasterization_state.depthBiasClamp = 0.0f; // dynamic depth bias state
|
||||||
rasterization_state.depthBiasSlopeFactor = 0.0f; // dynamic depth bias state
|
rasterization_state.depthBiasSlopeFactor = 0.0f; // dynamic depth bias state
|
||||||
|
|
@ -1305,9 +1283,9 @@ static VkPipeline create_pipeline(const Vk_Pipeline_Desc& desc) {
|
||||||
depth_stencil_state.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
|
depth_stencil_state.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
|
||||||
depth_stencil_state.pNext = nullptr;
|
depth_stencil_state.pNext = nullptr;
|
||||||
depth_stencil_state.flags = 0;
|
depth_stencil_state.flags = 0;
|
||||||
depth_stencil_state.depthTestEnable = (desc.state_bits & GLS_DEPTHTEST_DISABLE) ? VK_FALSE : VK_TRUE;
|
depth_stencil_state.depthTestEnable = (def.state_bits & GLS_DEPTHTEST_DISABLE) ? VK_FALSE : VK_TRUE;
|
||||||
depth_stencil_state.depthWriteEnable = (desc.state_bits & GLS_DEPTHMASK_TRUE) ? VK_TRUE : VK_FALSE;
|
depth_stencil_state.depthWriteEnable = (def.state_bits & GLS_DEPTHMASK_TRUE) ? VK_TRUE : VK_FALSE;
|
||||||
depth_stencil_state.depthCompareOp = (desc.state_bits & GLS_DEPTHFUNC_EQUAL) ? VK_COMPARE_OP_EQUAL : VK_COMPARE_OP_LESS_OR_EQUAL;
|
depth_stencil_state.depthCompareOp = (def.state_bits & GLS_DEPTHFUNC_EQUAL) ? VK_COMPARE_OP_EQUAL : VK_COMPARE_OP_LESS_OR_EQUAL;
|
||||||
depth_stencil_state.depthBoundsTestEnable = VK_FALSE;
|
depth_stencil_state.depthBoundsTestEnable = VK_FALSE;
|
||||||
depth_stencil_state.stencilTestEnable = VK_FALSE;
|
depth_stencil_state.stencilTestEnable = VK_FALSE;
|
||||||
depth_stencil_state.front = {};
|
depth_stencil_state.front = {};
|
||||||
|
|
@ -1316,11 +1294,11 @@ static VkPipeline create_pipeline(const Vk_Pipeline_Desc& desc) {
|
||||||
depth_stencil_state.maxDepthBounds = 0.0;
|
depth_stencil_state.maxDepthBounds = 0.0;
|
||||||
|
|
||||||
VkPipelineColorBlendAttachmentState attachment_blend_state = {};
|
VkPipelineColorBlendAttachmentState attachment_blend_state = {};
|
||||||
attachment_blend_state.blendEnable = (desc.state_bits & (GLS_SRCBLEND_BITS | GLS_DSTBLEND_BITS)) ? VK_TRUE : VK_FALSE;
|
attachment_blend_state.blendEnable = (def.state_bits & (GLS_SRCBLEND_BITS | GLS_DSTBLEND_BITS)) ? VK_TRUE : VK_FALSE;
|
||||||
attachment_blend_state.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
|
attachment_blend_state.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
|
||||||
|
|
||||||
if (attachment_blend_state.blendEnable) {
|
if (attachment_blend_state.blendEnable) {
|
||||||
switch (desc.state_bits & GLS_SRCBLEND_BITS) {
|
switch (def.state_bits & GLS_SRCBLEND_BITS) {
|
||||||
case GLS_SRCBLEND_ZERO:
|
case GLS_SRCBLEND_ZERO:
|
||||||
attachment_blend_state.srcColorBlendFactor = VK_BLEND_FACTOR_ZERO;
|
attachment_blend_state.srcColorBlendFactor = VK_BLEND_FACTOR_ZERO;
|
||||||
break;
|
break;
|
||||||
|
|
@ -1352,7 +1330,7 @@ static VkPipeline create_pipeline(const Vk_Pipeline_Desc& desc) {
|
||||||
ri.Error( ERR_DROP, "create_pipeline: invalid src blend state bits\n" );
|
ri.Error( ERR_DROP, "create_pipeline: invalid src blend state bits\n" );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
switch (desc.state_bits & GLS_DSTBLEND_BITS) {
|
switch (def.state_bits & GLS_DSTBLEND_BITS) {
|
||||||
case GLS_DSTBLEND_ZERO:
|
case GLS_DSTBLEND_ZERO:
|
||||||
attachment_blend_state.dstColorBlendFactor = VK_BLEND_FACTOR_ZERO;
|
attachment_blend_state.dstColorBlendFactor = VK_BLEND_FACTOR_ZERO;
|
||||||
break;
|
break;
|
||||||
|
|
@ -1447,22 +1425,75 @@ struct Timer {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
VkPipeline vk_find_pipeline(const Vk_Pipeline_Desc& desc) {
|
VkSampler vk_find_sampler(const Vk_Sampler_Def& def) {
|
||||||
|
// Look for sampler among existing samplers.
|
||||||
|
for (int i = 0; i < vk_resources.num_samplers; i++) {
|
||||||
|
const auto& cur_def = vk_resources.sampler_defs[i];
|
||||||
|
|
||||||
|
if (cur_def.repeat_texture == def.repeat_texture)
|
||||||
|
{
|
||||||
|
return vk_resources.samplers[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create new sampler.
|
||||||
|
if (vk_resources.num_samplers >= MAX_VK_SAMPLERS) {
|
||||||
|
ri.Error(ERR_DROP, "vk_find_sampler: MAX_VK_SAMPLERS hit\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
VkSamplerAddressMode address_mode = def.repeat_texture ? VK_SAMPLER_ADDRESS_MODE_REPEAT : VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
|
||||||
|
|
||||||
|
VkSamplerCreateInfo desc;
|
||||||
|
desc.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
|
||||||
|
desc.pNext = nullptr;
|
||||||
|
desc.flags = 0;
|
||||||
|
desc.magFilter = VK_FILTER_LINEAR;
|
||||||
|
desc.minFilter = VK_FILTER_LINEAR;
|
||||||
|
desc.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST;
|
||||||
|
desc.addressModeU = address_mode;
|
||||||
|
desc.addressModeV = address_mode;
|
||||||
|
desc.addressModeW = address_mode;
|
||||||
|
desc.mipLodBias = 0.0f;
|
||||||
|
desc.anisotropyEnable = VK_TRUE;
|
||||||
|
desc.maxAnisotropy = 1;
|
||||||
|
desc.compareEnable = VK_FALSE;
|
||||||
|
desc.compareOp = VK_COMPARE_OP_ALWAYS;
|
||||||
|
desc.minLod = 0.0f;
|
||||||
|
desc.maxLod = 12.0f;
|
||||||
|
desc.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK;
|
||||||
|
desc.unnormalizedCoordinates = VK_FALSE;
|
||||||
|
|
||||||
|
VkSampler sampler;
|
||||||
|
VK_CHECK(vkCreateSampler(vk.device, &desc, nullptr, &sampler));
|
||||||
|
|
||||||
|
vk_resources.sampler_defs[vk_resources.num_samplers] = def;
|
||||||
|
vk_resources.samplers[vk_resources.num_samplers] = sampler;
|
||||||
|
vk_resources.num_samplers++;
|
||||||
|
return sampler;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkPipeline vk_find_pipeline(const Vk_Pipeline_Def& def) {
|
||||||
for (int i = 0; i < vk_resources.num_pipelines; i++) {
|
for (int i = 0; i < vk_resources.num_pipelines; i++) {
|
||||||
if (vk_resources.pipeline_desc[i] == desc) {
|
const auto& cur_def = vk_resources.pipeline_defs[i];
|
||||||
|
|
||||||
|
if (cur_def.shader_type == def.shader_type &&
|
||||||
|
cur_def.state_bits == def.state_bits &&
|
||||||
|
cur_def.face_culling == def.face_culling &&
|
||||||
|
cur_def.polygon_offset == def.polygon_offset)
|
||||||
|
{
|
||||||
return vk_resources.pipelines[i];
|
return vk_resources.pipelines[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vk_resources.num_pipelines == MAX_VK_PIPELINES) {
|
if (vk_resources.num_pipelines >= MAX_VK_PIPELINES) {
|
||||||
ri.Error( ERR_DROP, "vk_find_pipeline: MAX_VK_PIPELINES hit\n");
|
ri.Error(ERR_DROP, "vk_find_pipeline: MAX_VK_PIPELINES hit\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
Timer t;
|
Timer t;
|
||||||
VkPipeline pipeline = create_pipeline(desc);
|
VkPipeline pipeline = create_pipeline(def);
|
||||||
pipeline_create_time += t.Elapsed_Seconds();
|
pipeline_create_time += t.Elapsed_Seconds();
|
||||||
|
|
||||||
vk_resources.pipeline_desc[vk_resources.num_pipelines] = desc;
|
vk_resources.pipeline_defs[vk_resources.num_pipelines] = def;
|
||||||
vk_resources.pipelines[vk_resources.num_pipelines] = pipeline;
|
vk_resources.pipelines[vk_resources.num_pipelines] = pipeline;
|
||||||
vk_resources.num_pipelines++;
|
vk_resources.num_pipelines++;
|
||||||
return pipeline;
|
return pipeline;
|
||||||
|
|
@ -1496,7 +1527,7 @@ VkRect2D vk_get_viewport_rect() {
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
void vk_get_mvp_transform(float mvp[16]) {
|
static void get_mvp_transform(float* mvp) {
|
||||||
if (backEnd.projection2D) {
|
if (backEnd.projection2D) {
|
||||||
float mvp0 = 2.0f / glConfig.vidWidth;
|
float mvp0 = 2.0f / glConfig.vidWidth;
|
||||||
float mvp5 = 2.0f / glConfig.vidHeight;
|
float mvp5 = 2.0f / glConfig.vidHeight;
|
||||||
|
|
@ -1554,7 +1585,7 @@ void vk_bind_resources_shared_between_stages() {
|
||||||
|
|
||||||
// update mvp transform
|
// update mvp transform
|
||||||
float mvp[16];
|
float mvp[16];
|
||||||
vk_get_mvp_transform(mvp);
|
get_mvp_transform(mvp);
|
||||||
vkCmdPushConstants(vk.command_buffer, vk.pipeline_layout, VK_SHADER_STAGE_VERTEX_BIT, 0, 64, mvp);
|
vkCmdPushConstants(vk.command_buffer, vk.pipeline_layout, VK_SHADER_STAGE_VERTEX_BIT, 0, 64, mvp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@
|
||||||
#include "vulkan/vulkan.h"
|
#include "vulkan/vulkan.h"
|
||||||
|
|
||||||
const int MAX_SWAPCHAIN_IMAGES = 8;
|
const int MAX_SWAPCHAIN_IMAGES = 8;
|
||||||
|
const int MAX_VK_SAMPLERS = 32;
|
||||||
const int MAX_VK_PIPELINES = 1024;
|
const int MAX_VK_PIPELINES = 1024;
|
||||||
const int MAX_VK_IMAGES = 2048; // should be the same as MAX_DRAWIMAGES
|
const int MAX_VK_IMAGES = 2048; // should be the same as MAX_DRAWIMAGES
|
||||||
|
|
||||||
|
|
@ -26,19 +27,15 @@ enum class Vk_Shader_Type {
|
||||||
multi_texture_add
|
multi_texture_add
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Vk_Pipeline_Desc {
|
struct Vk_Sampler_Def {
|
||||||
|
bool repeat_texture = false; // clamp/repeat texture addressing mode
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Vk_Pipeline_Def {
|
||||||
Vk_Shader_Type shader_type = Vk_Shader_Type::single_texture;
|
Vk_Shader_Type shader_type = Vk_Shader_Type::single_texture;
|
||||||
unsigned int state_bits = 0; // GLS_XXX flags
|
unsigned int state_bits = 0; // GLS_XXX flags
|
||||||
int face_culling = 0;// cullType_t
|
int face_culling = 0;// cullType_t
|
||||||
bool polygon_offset = false;
|
bool polygon_offset = false;
|
||||||
|
|
||||||
bool operator==(const Vk_Pipeline_Desc& other) const {
|
|
||||||
return
|
|
||||||
shader_type == other.shader_type &&
|
|
||||||
state_bits == other.state_bits &&
|
|
||||||
face_culling == other.face_culling &&
|
|
||||||
polygon_offset == other.polygon_offset;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Vk_Image {
|
struct Vk_Image {
|
||||||
|
|
@ -60,19 +57,17 @@ void vk_destroy_resources(); // destroys Vk_Resources resources
|
||||||
//
|
//
|
||||||
// Resources allocation.
|
// Resources allocation.
|
||||||
//
|
//
|
||||||
Vk_Image vk_create_image(int width, int height, int mip_levels);
|
Vk_Image vk_create_image(int width, int height, int mip_levels, bool repeat_texture);
|
||||||
void vk_upload_image_data(VkImage image, int width, int height, bool mipmap, const uint8_t* rgba_pixels);
|
void vk_upload_image_data(VkImage image, int width, int height, bool mipmap, const uint8_t* rgba_pixels);
|
||||||
VkPipeline vk_find_pipeline(const Vk_Pipeline_Desc& desc);
|
VkSampler vk_find_sampler(const Vk_Sampler_Def& def);
|
||||||
|
VkPipeline vk_find_pipeline(const Vk_Pipeline_Def& def);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Rendering setup.
|
// Rendering setup.
|
||||||
//
|
//
|
||||||
VkRect2D vk_get_viewport_rect();
|
VkRect2D vk_get_viewport_rect();
|
||||||
void vk_get_mvp_transform(float mvp[16]);
|
|
||||||
|
|
||||||
void vk_bind_resources_shared_between_stages();
|
void vk_bind_resources_shared_between_stages();
|
||||||
void vk_bind_stage_specific_resources(VkPipeline pipeline, bool multitexture, bool sky);
|
void vk_bind_stage_specific_resources(VkPipeline pipeline, bool multitexture, bool sky);
|
||||||
|
|
||||||
void vk_begin_frame();
|
void vk_begin_frame();
|
||||||
void vk_end_frame();
|
void vk_end_frame();
|
||||||
|
|
||||||
|
|
@ -130,17 +125,26 @@ struct Vk_Instance {
|
||||||
VkShaderModule multi_texture_mul_fs = VK_NULL_HANDLE;
|
VkShaderModule multi_texture_mul_fs = VK_NULL_HANDLE;
|
||||||
VkShaderModule multi_texture_add_fs = VK_NULL_HANDLE;
|
VkShaderModule multi_texture_add_fs = VK_NULL_HANDLE;
|
||||||
|
|
||||||
VkSampler sampler = VK_NULL_HANDLE;
|
|
||||||
VkPipeline skybox_pipeline = VK_NULL_HANDLE;
|
VkPipeline skybox_pipeline = VK_NULL_HANDLE;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Vk_Resources {
|
struct Vk_Resources {
|
||||||
|
//
|
||||||
|
// Resources.
|
||||||
|
//
|
||||||
|
int num_samplers = 0;
|
||||||
|
Vk_Sampler_Def sampler_defs[MAX_VK_SAMPLERS];
|
||||||
|
VkSampler samplers[MAX_VK_SAMPLERS];
|
||||||
|
|
||||||
int num_pipelines = 0;
|
int num_pipelines = 0;
|
||||||
Vk_Pipeline_Desc pipeline_desc[MAX_VK_PIPELINES];
|
Vk_Pipeline_Def pipeline_defs[MAX_VK_PIPELINES];
|
||||||
VkPipeline pipelines[MAX_VK_PIPELINES];
|
VkPipeline pipelines[MAX_VK_PIPELINES];
|
||||||
|
|
||||||
Vk_Image images[MAX_VK_IMAGES];
|
Vk_Image images[MAX_VK_IMAGES];
|
||||||
|
|
||||||
|
//
|
||||||
|
// Memory allocations.
|
||||||
|
//
|
||||||
struct Chunk {
|
struct Chunk {
|
||||||
VkDeviceMemory memory = VK_NULL_HANDLE;
|
VkDeviceMemory memory = VK_NULL_HANDLE;
|
||||||
VkDeviceSize used = 0;
|
VkDeviceSize used = 0;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user