Texture addressing mode selection (repeat or clamp).

This commit is contained in:
Artem Kharytoniuk 2017-04-27 12:20:06 +03:00
parent 327ebe2daf
commit 4d33fcf925
5 changed files with 143 additions and 104 deletions

View File

@ -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) {

View File

@ -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) {

View File

@ -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();

View File

@ -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);
} }

View File

@ -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;