Store vertex attributes in SOA style: continuous region of vertex buffer per attribute.
Removed structures that specified different vertex format.
This commit is contained in:
parent
047be0bd46
commit
eac342cdd9
|
|
@ -1063,7 +1063,13 @@ const void *RB_SwapBuffers( const void *data ) {
|
||||||
// VULKAN
|
// VULKAN
|
||||||
extern FILE* vk_log_file;
|
extern FILE* vk_log_file;
|
||||||
|
|
||||||
vulkan_demo->end_frame();
|
if (r_logFile->integer)
|
||||||
|
fprintf(vk_log_file, "end_frame (vb_size %d, ib_size %d)\n",
|
||||||
|
vk.xyz_elements * 16 + vk.color_st_elements * 20,
|
||||||
|
(int)vk.index_buffer_offset);
|
||||||
|
|
||||||
|
vkCmdEndRenderPass(vk.command_buffer);
|
||||||
|
|
||||||
VkResult result = vkEndCommandBuffer(vk.command_buffer);
|
VkResult result = vkEndCommandBuffer(vk.command_buffer);
|
||||||
check_vk_result(result, "vkEndCommandBuffer");
|
check_vk_result(result, "vkEndCommandBuffer");
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -791,6 +791,9 @@ static void ComputeTexCoords( shaderStage_t *pStage ) {
|
||||||
*/
|
*/
|
||||||
static void RB_IterateStagesGeneric( shaderCommands_t *input )
|
static void RB_IterateStagesGeneric( shaderCommands_t *input )
|
||||||
{
|
{
|
||||||
|
// VULKAN
|
||||||
|
vk_bind_resources_shared_between_stages(input->numPasses);
|
||||||
|
|
||||||
for ( int stage = 0; stage < MAX_SHADER_STAGES; stage++ )
|
for ( int stage = 0; stage < MAX_SHADER_STAGES; stage++ )
|
||||||
{
|
{
|
||||||
shaderStage_t *pStage = tess.xstages[stage];
|
shaderStage_t *pStage = tess.xstages[stage];
|
||||||
|
|
@ -838,7 +841,9 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input )
|
||||||
}
|
}
|
||||||
|
|
||||||
// VULKAN
|
// VULKAN
|
||||||
vk_draw(pStage->vk_pipeline, multitexture);
|
vk_bind_stage_specific_resources(pStage->vk_pipeline, multitexture);
|
||||||
|
vkCmdDrawIndexed(vk.command_buffer, tess.numIndexes, 1, 0, 0, 0);
|
||||||
|
glState.vk_dirty_attachments = true;
|
||||||
|
|
||||||
// allow skipping out to show just lightmaps during development
|
// allow skipping out to show just lightmaps during development
|
||||||
if ( r_lightmap->integer && ( pStage->bundle[0].isLightmap || pStage->bundle[1].isLightmap ) )
|
if ( r_lightmap->integer && ( pStage->bundle[0].isLightmap || pStage->bundle[1].isLightmap ) )
|
||||||
|
|
@ -846,6 +851,9 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input )
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// VULKAN
|
||||||
|
vk.xyz_elements += tess.numVertexes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,14 +6,21 @@
|
||||||
|
|
||||||
#include "vk_demo.h"
|
#include "vk_demo.h"
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <cassert>
|
|
||||||
#include <iostream>
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
static const int VERTEX_BUFFER_SIZE = 4 * 1024 * 1024;
|
const int VERTEX_CHUNK_SIZE = 512 * 1024;
|
||||||
|
|
||||||
|
const int XYZ_SIZE = 4 * VERTEX_CHUNK_SIZE;
|
||||||
|
const int COLOR_SIZE = 1 * VERTEX_CHUNK_SIZE;
|
||||||
|
const int ST0_SIZE = 2 * VERTEX_CHUNK_SIZE;
|
||||||
|
const int ST1_SIZE = 2 * VERTEX_CHUNK_SIZE;
|
||||||
|
|
||||||
|
const int XYZ_OFFSET = 0;
|
||||||
|
const int COLOR_OFFSET = XYZ_OFFSET + XYZ_SIZE;
|
||||||
|
const int ST0_OFFSET = COLOR_OFFSET + COLOR_SIZE;
|
||||||
|
const int ST1_OFFSET = ST0_OFFSET + ST0_SIZE;
|
||||||
|
|
||||||
|
static const int VERTEX_BUFFER_SIZE = XYZ_SIZE + COLOR_SIZE + ST0_SIZE + ST1_SIZE;
|
||||||
static const int INDEX_BUFFER_SIZE = 2 * 1024 * 1024;
|
static const int INDEX_BUFFER_SIZE = 2 * 1024 * 1024;
|
||||||
|
|
||||||
static const std::vector<const char*> instance_extensions = {
|
static const std::vector<const char*> instance_extensions = {
|
||||||
|
|
@ -510,6 +517,11 @@ bool vk_initialize(HWND hwnd) {
|
||||||
vk.vertex_buffer_memory = get_allocator()->allocate_staging_memory(vk.vertex_buffer);
|
vk.vertex_buffer_memory = get_allocator()->allocate_staging_memory(vk.vertex_buffer);
|
||||||
result = vkBindBufferMemory(vk.device, vk.vertex_buffer, vk.vertex_buffer_memory, 0);
|
result = vkBindBufferMemory(vk.device, vk.vertex_buffer, vk.vertex_buffer_memory, 0);
|
||||||
check_vk_result(result, "vkBindBufferMemory");
|
check_vk_result(result, "vkBindBufferMemory");
|
||||||
|
|
||||||
|
void* data;
|
||||||
|
result = vkMapMemory(vk.device, vk.vertex_buffer_memory, 0, VERTEX_BUFFER_SIZE, 0, &data);
|
||||||
|
check_vk_result(result, "vkMapMemory");
|
||||||
|
vk.vertex_buffer_ptr = (byte*)data;
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
VkBufferCreateInfo desc;
|
VkBufferCreateInfo desc;
|
||||||
|
|
@ -528,6 +540,11 @@ bool vk_initialize(HWND hwnd) {
|
||||||
vk.index_buffer_memory = get_allocator()->allocate_staging_memory(vk.index_buffer);
|
vk.index_buffer_memory = get_allocator()->allocate_staging_memory(vk.index_buffer);
|
||||||
result = vkBindBufferMemory(vk.device, vk.index_buffer, vk.index_buffer_memory, 0);
|
result = vkBindBufferMemory(vk.device, vk.index_buffer, vk.index_buffer_memory, 0);
|
||||||
check_vk_result(result, "vkBindBufferMemory");
|
check_vk_result(result, "vkBindBufferMemory");
|
||||||
|
|
||||||
|
void* data;
|
||||||
|
result = vkMapMemory(vk.device, vk.index_buffer_memory, 0, INDEX_BUFFER_SIZE, 0, &data);
|
||||||
|
check_vk_result(result, "vkMapMemory");
|
||||||
|
vk.index_buffer_ptr = (byte*)data;
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (const std::exception&) {
|
} catch (const std::exception&) {
|
||||||
|
|
@ -718,28 +735,67 @@ static VkPipeline create_pipeline(const Vk_Pipeline_Desc& desc) {
|
||||||
if (desc.state_bits & GLS_ATEST_BITS)
|
if (desc.state_bits & GLS_ATEST_BITS)
|
||||||
shader_stages_state.back().pSpecializationInfo = &specialization_info;
|
shader_stages_state.back().pSpecializationInfo = &specialization_info;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Vertex input
|
||||||
|
//
|
||||||
|
VkVertexInputBindingDescription bindings[4];
|
||||||
|
// xyz array
|
||||||
|
bindings[0].binding = 0;
|
||||||
|
bindings[0].stride = sizeof(vec4_t);
|
||||||
|
bindings[0].inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
|
||||||
|
|
||||||
|
// color array
|
||||||
|
bindings[1].binding = 1;
|
||||||
|
bindings[1].stride = sizeof(color4ub_t);
|
||||||
|
bindings[1].inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
|
||||||
|
|
||||||
|
// st0 array
|
||||||
|
bindings[2].binding = 2;
|
||||||
|
bindings[2].stride = sizeof(vec2_t);
|
||||||
|
bindings[2].inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
|
||||||
|
|
||||||
|
// st1 array
|
||||||
|
bindings[3].binding = 3;
|
||||||
|
bindings[3].stride = sizeof(vec2_t);
|
||||||
|
bindings[3].inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
|
||||||
|
|
||||||
|
VkVertexInputAttributeDescription attribs[4];
|
||||||
|
// xyz
|
||||||
|
attribs[0].location = 0;
|
||||||
|
attribs[0].binding = 0;
|
||||||
|
attribs[0].format = VK_FORMAT_R32G32B32A32_SFLOAT;
|
||||||
|
attribs[0].offset = 0;
|
||||||
|
|
||||||
|
// color
|
||||||
|
attribs[1].location = 1;
|
||||||
|
attribs[1].binding = 1;
|
||||||
|
attribs[1].format = VK_FORMAT_R8G8B8A8_UNORM;
|
||||||
|
attribs[1].offset = 0;
|
||||||
|
|
||||||
|
// st0
|
||||||
|
attribs[2].location = 2;
|
||||||
|
attribs[2].binding = 2;
|
||||||
|
attribs[2].format = VK_FORMAT_R32G32_SFLOAT;
|
||||||
|
attribs[2].offset = 0;
|
||||||
|
|
||||||
|
// st1
|
||||||
|
attribs[3].location = 3;
|
||||||
|
attribs[3].binding = 3;
|
||||||
|
attribs[3].format = VK_FORMAT_R32G32_SFLOAT;
|
||||||
|
attribs[3].offset = 0;
|
||||||
|
|
||||||
VkPipelineVertexInputStateCreateInfo vertex_input_state;
|
VkPipelineVertexInputStateCreateInfo vertex_input_state;
|
||||||
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.pVertexBindingDescriptions = bindings;
|
||||||
|
vertex_input_state.vertexAttributeDescriptionCount = (desc.shader_type == Vk_Shader_Type::single_texture) ? 3 : 4;
|
||||||
|
vertex_input_state.pVertexAttributeDescriptions = attribs;
|
||||||
|
|
||||||
auto bindings = Vk_Vertex::get_bindings();
|
//
|
||||||
auto attribs = Vk_Vertex::get_attributes();
|
// Primitive assembly.
|
||||||
auto bindings2 = Vk_Vertex2::get_bindings();
|
//
|
||||||
auto attribs2 = Vk_Vertex2::get_attributes();
|
|
||||||
|
|
||||||
if (desc.shader_type == Vk_Shader_Type::single_texture) {
|
|
||||||
vertex_input_state.vertexBindingDescriptionCount = (uint32_t)bindings.size();
|
|
||||||
vertex_input_state.pVertexBindingDescriptions = bindings.data();
|
|
||||||
vertex_input_state.vertexAttributeDescriptionCount = (uint32_t)attribs.size();
|
|
||||||
vertex_input_state.pVertexAttributeDescriptions = attribs.data();
|
|
||||||
} else {
|
|
||||||
vertex_input_state.vertexBindingDescriptionCount = (uint32_t)bindings2.size();
|
|
||||||
vertex_input_state.pVertexBindingDescriptions = bindings2.data();
|
|
||||||
vertex_input_state.vertexAttributeDescriptionCount = (uint32_t)attribs2.size();
|
|
||||||
vertex_input_state.pVertexAttributeDescriptions = attribs2.data();
|
|
||||||
}
|
|
||||||
|
|
||||||
VkPipelineInputAssemblyStateCreateInfo input_assembly_state;
|
VkPipelineInputAssemblyStateCreateInfo input_assembly_state;
|
||||||
input_assembly_state.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
|
input_assembly_state.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
|
||||||
input_assembly_state.pNext = nullptr;
|
input_assembly_state.pNext = nullptr;
|
||||||
|
|
@ -747,6 +803,9 @@ static VkPipeline create_pipeline(const Vk_Pipeline_Desc& desc) {
|
||||||
input_assembly_state.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
|
input_assembly_state.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
|
||||||
input_assembly_state.primitiveRestartEnable = VK_FALSE;
|
input_assembly_state.primitiveRestartEnable = VK_FALSE;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Viewport.
|
||||||
|
//
|
||||||
VkPipelineViewportStateCreateInfo viewport_state;
|
VkPipelineViewportStateCreateInfo viewport_state;
|
||||||
viewport_state.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
|
viewport_state.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
|
||||||
viewport_state.pNext = nullptr;
|
viewport_state.pNext = nullptr;
|
||||||
|
|
@ -756,6 +815,9 @@ static VkPipeline create_pipeline(const Vk_Pipeline_Desc& desc) {
|
||||||
viewport_state.scissorCount = 1;
|
viewport_state.scissorCount = 1;
|
||||||
viewport_state.pScissors = nullptr; // dynamic scissor state
|
viewport_state.pScissors = nullptr; // dynamic scissor state
|
||||||
|
|
||||||
|
//
|
||||||
|
// Rasterization.
|
||||||
|
//
|
||||||
VkPipelineRasterizationStateCreateInfo rasterization_state;
|
VkPipelineRasterizationStateCreateInfo rasterization_state;
|
||||||
rasterization_state.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
|
rasterization_state.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
|
||||||
rasterization_state.pNext = nullptr;
|
rasterization_state.pNext = nullptr;
|
||||||
|
|
@ -1011,7 +1073,8 @@ void vk_destroy_resources() {
|
||||||
vkDeviceWaitIdle(vk.device);
|
vkDeviceWaitIdle(vk.device);
|
||||||
vk_destroy_pipelines();
|
vk_destroy_pipelines();
|
||||||
|
|
||||||
vk.vertex_buffer_offset = 0;
|
vk.xyz_elements = 0;
|
||||||
|
vk.color_st_elements = 0;
|
||||||
vk.index_buffer_offset = 0;
|
vk.index_buffer_offset = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1075,60 +1138,32 @@ void vk_get_mvp_transform(float mvp[16]) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void vk_draw(VkPipeline pipeline, bool multitexture) {
|
void vk_bind_resources_shared_between_stages(int num_passes) {
|
||||||
extern FILE* vk_log_file;
|
extern FILE* vk_log_file;
|
||||||
if (r_logFile->integer)
|
if (r_logFile->integer)
|
||||||
fprintf(vk_log_file, "render_tess (%s, vert %d, inds %d)\n", multitexture ? "M" : "S", tess.numVertexes, tess.numIndexes);
|
fprintf(vk_log_file, "render_tess (passes %d, vert %d, inds %d)\n", num_passes, tess.numVertexes, tess.numIndexes);
|
||||||
|
|
||||||
auto vertex_size = multitexture ? sizeof(Vk_Vertex2) : sizeof(Vk_Vertex);
|
// xyz
|
||||||
|
{
|
||||||
|
if ((vk.xyz_elements + tess.numVertexes) * sizeof(vec4_t) > XYZ_SIZE)
|
||||||
|
ri.Error(ERR_DROP, "vulkan: vertex buffer overflow (xyz)\n");
|
||||||
|
|
||||||
// update vertex buffer
|
byte* dst = vk.vertex_buffer_ptr + XYZ_OFFSET + vk.xyz_elements * sizeof(vec4_t);
|
||||||
std::size_t vertexes_size = tess.numVertexes * vertex_size;
|
Com_Memcpy(dst, tess.xyz, tess.numVertexes * sizeof(vec4_t));
|
||||||
if (vk.vertex_buffer_offset + vertexes_size > VERTEX_BUFFER_SIZE)
|
|
||||||
ri.Error(ERR_DROP, "vk_draw: vertex buffer overflow\n");
|
|
||||||
|
|
||||||
void* data;
|
|
||||||
VkResult result = vkMapMemory(vk.device, vk.vertex_buffer_memory, vk.vertex_buffer_offset, vertexes_size, 0, &data);
|
|
||||||
check_vk_result(result, "vkMapMemory");
|
|
||||||
Timer t;
|
|
||||||
unsigned char* ptr = (unsigned char*)data;
|
|
||||||
for (int i = 0; i < tess.numVertexes; i++, ptr += vertex_size) {
|
|
||||||
Vk_Vertex* v = (Vk_Vertex*)ptr;
|
|
||||||
v->pos[0] = tess.xyz[i][0];
|
|
||||||
v->pos[1] = tess.xyz[i][1];
|
|
||||||
v->pos[2] = tess.xyz[i][2];
|
|
||||||
v->color[0] = tess.svars.colors[i][0];
|
|
||||||
v->color[1] = tess.svars.colors[i][1];
|
|
||||||
v->color[2] = tess.svars.colors[i][2];
|
|
||||||
v->color[3] = tess.svars.colors[i][3];
|
|
||||||
v->st[0] = tess.svars.texcoords[0][i][0];
|
|
||||||
v->st[1] = tess.svars.texcoords[0][i][1];
|
|
||||||
|
|
||||||
if (multitexture) {
|
|
||||||
auto v2 = (Vk_Vertex2*)ptr;
|
|
||||||
v2->st2[0] = tess.svars.texcoords[1][i][0];
|
|
||||||
v2->st2[1] = tess.svars.texcoords[1][i][1];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
vulkan_demo->vertex_copy_time += t.Elapsed_Seconds();
|
|
||||||
vkUnmapMemory(vk.device, vk.vertex_buffer_memory);
|
|
||||||
|
|
||||||
vkCmdBindVertexBuffers(vk.command_buffer, 0, 1, &vk.vertex_buffer, &vk.vertex_buffer_offset);
|
std::size_t indexes_size = tess.numIndexes * sizeof(uint32_t);
|
||||||
vk.vertex_buffer_offset += vertexes_size;
|
|
||||||
|
|
||||||
// update index buffer
|
// update index buffer
|
||||||
std::size_t indexes_size = tess.numIndexes * sizeof(uint32_t);
|
{
|
||||||
if (vk.index_buffer_offset + indexes_size > INDEX_BUFFER_SIZE)
|
if (vk.index_buffer_offset + indexes_size > INDEX_BUFFER_SIZE)
|
||||||
ri.Error(ERR_DROP, "vk_draw: index buffer overflow\n");
|
ri.Error(ERR_DROP, "vk_draw: index buffer overflow\n");
|
||||||
|
|
||||||
result = vkMapMemory(vk.device, vk.index_buffer_memory, vk.index_buffer_offset, indexes_size, 0, &data);
|
byte* dst = vk.index_buffer_ptr + vk.index_buffer_offset;
|
||||||
check_vk_result(result, "vkMapMemory");
|
Com_Memcpy(dst, tess.indexes, indexes_size);
|
||||||
uint32_t* ind = (uint32_t*)data;
|
|
||||||
for (int i = 0; i < tess.numIndexes; i++, ind++) {
|
|
||||||
*ind = tess.indexes[i];
|
|
||||||
}
|
}
|
||||||
vkUnmapMemory(vk.device, vk.index_buffer_memory);
|
|
||||||
|
|
||||||
|
// configure indexes stream
|
||||||
vkCmdBindIndexBuffer(vk.command_buffer, vk.index_buffer, vk.index_buffer_offset, VK_INDEX_TYPE_UINT32);
|
vkCmdBindIndexBuffer(vk.command_buffer, vk.index_buffer, vk.index_buffer_offset, VK_INDEX_TYPE_UINT32);
|
||||||
vk.index_buffer_offset += indexes_size;
|
vk.index_buffer_offset += indexes_size;
|
||||||
|
|
||||||
|
|
@ -1136,15 +1171,63 @@ void vk_draw(VkPipeline pipeline, bool multitexture) {
|
||||||
float mvp[16];
|
float mvp[16];
|
||||||
vk_get_mvp_transform(mvp);
|
vk_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);
|
||||||
|
}
|
||||||
|
|
||||||
|
void vk_bind_stage_specific_resources(VkPipeline pipeline, bool multitexture) {
|
||||||
|
//
|
||||||
|
// Specify color/st for each draw call since they are regenerated for each Q3 shader's stage.
|
||||||
|
// xyz are specified only once for all stages.
|
||||||
|
//
|
||||||
|
|
||||||
|
// color
|
||||||
|
{
|
||||||
|
if ((vk.color_st_elements + tess.numVertexes) * sizeof(color4ub_t) > COLOR_SIZE)
|
||||||
|
ri.Error(ERR_DROP, "vulkan: vertex buffer overflow (color)\n");
|
||||||
|
|
||||||
|
byte* dst = vk.vertex_buffer_ptr + COLOR_OFFSET + vk.color_st_elements * sizeof(color4ub_t);
|
||||||
|
Com_Memcpy(dst, tess.svars.colors, tess.numVertexes * sizeof(color4ub_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
// st0
|
||||||
|
{
|
||||||
|
if ((vk.color_st_elements + tess.numVertexes) * sizeof(vec2_t) > ST0_SIZE)
|
||||||
|
ri.Error(ERR_DROP, "vulkan: vertex buffer overflow (st0)\n");
|
||||||
|
|
||||||
|
byte* dst = vk.vertex_buffer_ptr + ST0_OFFSET + vk.color_st_elements * sizeof(vec2_t);
|
||||||
|
Com_Memcpy(dst, tess.svars.texcoords[0], tess.numVertexes * sizeof(vec2_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
// st1
|
||||||
|
if (multitexture) {
|
||||||
|
if ((vk.color_st_elements + tess.numVertexes) * sizeof(vec2_t) > ST1_SIZE)
|
||||||
|
ri.Error(ERR_DROP, "vulkan: vertex buffer overflow (st1)\n");
|
||||||
|
|
||||||
|
byte* dst = vk.vertex_buffer_ptr + ST1_OFFSET + vk.color_st_elements * sizeof(vec2_t);
|
||||||
|
Com_Memcpy(dst, tess.svars.texcoords[1], tess.numVertexes * sizeof(vec2_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
// configure vertex data stream
|
||||||
|
VkBuffer bufs[4] = { vk.vertex_buffer, vk.vertex_buffer, vk.vertex_buffer, vk.vertex_buffer }; // turtles all the way down
|
||||||
|
VkDeviceSize offs[4] = {
|
||||||
|
XYZ_OFFSET + vk.xyz_elements * sizeof(vec4_t),
|
||||||
|
COLOR_OFFSET + vk.color_st_elements * sizeof(color4ub_t),
|
||||||
|
ST0_OFFSET + vk.color_st_elements * sizeof(vec2_t),
|
||||||
|
ST1_OFFSET + vk.color_st_elements * sizeof(vec2_t)
|
||||||
|
};
|
||||||
|
|
||||||
|
vkCmdBindVertexBuffers(vk.command_buffer, 0, multitexture ? 4 : 3, bufs, offs);
|
||||||
|
vk.color_st_elements += tess.numVertexes;
|
||||||
|
|
||||||
|
// bind descriptor sets
|
||||||
image_t* image = glState.vk_current_images[0];
|
image_t* image = glState.vk_current_images[0];
|
||||||
image_t* image2 = glState.vk_current_images[1];
|
image_t* image2 = glState.vk_current_images[1];
|
||||||
VkDescriptorSet sets[2] = { image->vk_descriptor_set, image2 ? image2->vk_descriptor_set : VkDescriptorSet() };
|
VkDescriptorSet sets[2] = { image->vk_descriptor_set, image2 ? image2->vk_descriptor_set : VkDescriptorSet() };
|
||||||
int set_count = multitexture ? 2 : 1;
|
vkCmdBindDescriptorSets(vk.command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, vk.pipeline_layout, 0, multitexture ? 2 : 1, sets, 0, nullptr);
|
||||||
vkCmdBindDescriptorSets(vk.command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, vk.pipeline_layout, 0, set_count, sets, 0, nullptr);
|
|
||||||
|
|
||||||
|
// bind pipeline
|
||||||
vkCmdBindPipeline(vk.command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
|
vkCmdBindPipeline(vk.command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
|
||||||
|
|
||||||
|
// configure pipeline's dynamic state
|
||||||
VkRect2D r = vk_get_viewport_rect();
|
VkRect2D r = vk_get_viewport_rect();
|
||||||
vkCmdSetScissor(vk.command_buffer, 0, 1, &r);
|
vkCmdSetScissor(vk.command_buffer, 0, 1, &r);
|
||||||
|
|
||||||
|
|
@ -1160,9 +1243,4 @@ void vk_draw(VkPipeline pipeline, bool multitexture) {
|
||||||
if (tess.shader->polygonOffset) {
|
if (tess.shader->polygonOffset) {
|
||||||
vkCmdSetDepthBias(vk.command_buffer, r_offsetUnits->value, 0.0f, r_offsetFactor->value);
|
vkCmdSetDepthBias(vk.command_buffer, r_offsetUnits->value, 0.0f, r_offsetFactor->value);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw primitives
|
|
||||||
vkCmdDrawIndexed(vk.command_buffer, tess.numIndexes, 1, 0, 0, 0);
|
|
||||||
|
|
||||||
glState.vk_dirty_attachments = true;
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,8 @@ void vk_destroy_resources();
|
||||||
VkRect2D vk_get_viewport_rect();
|
VkRect2D vk_get_viewport_rect();
|
||||||
void vk_get_mvp_transform(float mvp[16]);
|
void vk_get_mvp_transform(float mvp[16]);
|
||||||
|
|
||||||
void vk_draw(VkPipeline pipeline, bool multitexture);
|
void vk_bind_resources_shared_between_stages(int num_passes);
|
||||||
|
void vk_bind_stage_specific_resources(VkPipeline pipeline, bool multitexture);
|
||||||
|
|
||||||
struct Vk_Staging_Buffer {
|
struct Vk_Staging_Buffer {
|
||||||
VkBuffer handle = VK_NULL_HANDLE;
|
VkBuffer handle = VK_NULL_HANDLE;
|
||||||
|
|
@ -56,71 +57,6 @@ VkPipeline vk_find_pipeline(const Vk_Pipeline_Desc& desc);
|
||||||
|
|
||||||
VkDescriptorSet vk_create_descriptor_set(VkImageView image_view);
|
VkDescriptorSet vk_create_descriptor_set(VkImageView image_view);
|
||||||
|
|
||||||
// Vertex formats
|
|
||||||
struct Vk_Vertex {
|
|
||||||
vec3_t pos;
|
|
||||||
unsigned char color[4];
|
|
||||||
vec2_t st;
|
|
||||||
|
|
||||||
static std::array<VkVertexInputBindingDescription, 1> get_bindings() {
|
|
||||||
VkVertexInputBindingDescription binding_desc;
|
|
||||||
binding_desc.binding = 0;
|
|
||||||
binding_desc.stride = sizeof(Vk_Vertex);
|
|
||||||
binding_desc.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
|
|
||||||
return {binding_desc};
|
|
||||||
}
|
|
||||||
static std::array<VkVertexInputAttributeDescription, 3> get_attributes() {
|
|
||||||
VkVertexInputAttributeDescription position_attrib;
|
|
||||||
position_attrib.location = 0;
|
|
||||||
position_attrib.binding = 0;
|
|
||||||
position_attrib.format = VK_FORMAT_R32G32B32_SFLOAT;
|
|
||||||
position_attrib.offset = offsetof(struct Vk_Vertex, pos);
|
|
||||||
|
|
||||||
VkVertexInputAttributeDescription color_attrib;
|
|
||||||
color_attrib.location = 1;
|
|
||||||
color_attrib.binding = 0;
|
|
||||||
color_attrib.format = VK_FORMAT_R8G8B8A8_UNORM;
|
|
||||||
color_attrib.offset = offsetof(struct Vk_Vertex, color);
|
|
||||||
|
|
||||||
VkVertexInputAttributeDescription st_attrib;
|
|
||||||
st_attrib.location = 2;
|
|
||||||
st_attrib.binding = 0;
|
|
||||||
st_attrib.format = VK_FORMAT_R32G32_SFLOAT;
|
|
||||||
st_attrib.offset = offsetof(struct Vk_Vertex, st);
|
|
||||||
|
|
||||||
return {position_attrib, color_attrib, st_attrib};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Vk_Vertex2 : Vk_Vertex {
|
|
||||||
vec2_t st2;
|
|
||||||
|
|
||||||
static std::array<VkVertexInputBindingDescription, 1> get_bindings() {
|
|
||||||
VkVertexInputBindingDescription binding_desc;
|
|
||||||
binding_desc.binding = 0;
|
|
||||||
binding_desc.stride = sizeof(Vk_Vertex2);
|
|
||||||
binding_desc.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
|
|
||||||
return {binding_desc};
|
|
||||||
}
|
|
||||||
static std::array<VkVertexInputAttributeDescription, 4> get_attributes() {
|
|
||||||
auto vk_vertex_attribs = Vk_Vertex::get_attributes();
|
|
||||||
|
|
||||||
std::array<VkVertexInputAttributeDescription, 4> result;
|
|
||||||
result[0] = vk_vertex_attribs[0];
|
|
||||||
result[1] = vk_vertex_attribs[1];
|
|
||||||
result[2] = vk_vertex_attribs[2];
|
|
||||||
|
|
||||||
VkVertexInputAttributeDescription st2_attrib;
|
|
||||||
st2_attrib.location = 3;
|
|
||||||
st2_attrib.binding = 0;
|
|
||||||
st2_attrib.format = VK_FORMAT_R32G32_SFLOAT;
|
|
||||||
st2_attrib.offset = offsetof(struct Vk_Vertex2, st2);
|
|
||||||
result[3] = st2_attrib;
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Shaders.
|
// Shaders.
|
||||||
extern unsigned char single_texture_vert_spv[];
|
extern unsigned char single_texture_vert_spv[];
|
||||||
extern long long single_texture_vert_spv_size;
|
extern long long single_texture_vert_spv_size;
|
||||||
|
|
@ -170,10 +106,13 @@ struct Vulkan_Instance {
|
||||||
|
|
||||||
VkBuffer vertex_buffer = VK_NULL_HANDLE;
|
VkBuffer vertex_buffer = VK_NULL_HANDLE;
|
||||||
VkDeviceMemory vertex_buffer_memory = VK_NULL_HANDLE;
|
VkDeviceMemory vertex_buffer_memory = VK_NULL_HANDLE;
|
||||||
VkDeviceSize vertex_buffer_offset = 0;
|
byte* vertex_buffer_ptr = nullptr; // pointer to mapped vertex buffer
|
||||||
|
int xyz_elements = 0;
|
||||||
|
int color_st_elements = 0;
|
||||||
|
|
||||||
VkBuffer index_buffer = VK_NULL_HANDLE;
|
VkBuffer index_buffer = VK_NULL_HANDLE;
|
||||||
VkDeviceMemory index_buffer_memory = VK_NULL_HANDLE;
|
VkDeviceMemory index_buffer_memory = VK_NULL_HANDLE;
|
||||||
|
byte* index_buffer_ptr = nullptr; // pointer to mapped index buffer
|
||||||
VkDeviceSize index_buffer_offset = 0;
|
VkDeviceSize index_buffer_offset = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -183,4 +122,6 @@ struct Vulkan_Resources {
|
||||||
int num_pipelines = 0;
|
int num_pipelines = 0;
|
||||||
Vk_Pipeline_Desc pipeline_desc[MAX_VK_PIPELINES];
|
Vk_Pipeline_Desc pipeline_desc[MAX_VK_PIPELINES];
|
||||||
VkPipeline pipelines[MAX_VK_PIPELINES];
|
VkPipeline pipelines[MAX_VK_PIPELINES];
|
||||||
|
|
||||||
|
// TODO: put images here too.
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -128,15 +128,9 @@ void Vulkan_Demo::begin_frame() {
|
||||||
|
|
||||||
vkCmdBeginRenderPass(vk.command_buffer, &render_pass_begin_info, VK_SUBPASS_CONTENTS_INLINE);
|
vkCmdBeginRenderPass(vk.command_buffer, &render_pass_begin_info, VK_SUBPASS_CONTENTS_INLINE);
|
||||||
|
|
||||||
vk.vertex_buffer_offset = 0;
|
vk.xyz_elements = 0;
|
||||||
|
vk.color_st_elements = 0;
|
||||||
vk.index_buffer_offset = 0;
|
vk.index_buffer_offset = 0;
|
||||||
|
|
||||||
glState.vk_dirty_attachments = false;
|
glState.vk_dirty_attachments = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Vulkan_Demo::end_frame() {
|
|
||||||
if (r_logFile->integer)
|
|
||||||
fprintf(vk_log_file, "end_frame (vb_size %d, ib_size %d, copy_time %d)\n", (int)vk.vertex_buffer_offset, (int)vk.index_buffer_offset, int(vertex_copy_time * 1000000000));
|
|
||||||
vertex_copy_time = 0.0f;
|
|
||||||
vkCmdEndRenderPass(vk.command_buffer);
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,6 @@ public:
|
||||||
Vulkan_Demo(int window_width, int window_height);
|
Vulkan_Demo(int window_width, int window_height);
|
||||||
|
|
||||||
void begin_frame();
|
void begin_frame();
|
||||||
void end_frame();
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
VkImage create_texture(const uint8_t* pixels, int bytes_per_pixel, int width, int height, VkImageView& image_view);
|
VkImage create_texture(const uint8_t* pixels, int bytes_per_pixel, int width, int height, VkImageView& image_view);
|
||||||
|
|
@ -30,5 +29,4 @@ public:
|
||||||
VkSampler texture_image_sampler = VK_NULL_HANDLE;
|
VkSampler texture_image_sampler = VK_NULL_HANDLE;
|
||||||
|
|
||||||
uint32_t swapchain_image_index = -1;
|
uint32_t swapchain_image_index = -1;
|
||||||
double vertex_copy_time = 0.0f;
|
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user