@@ -25,6 +25,11 @@ VulkanBuffer vertexBuffer;
2525VulkanBuffer indexBuffer;
2626VulkanImage image;
2727
28+ VkSampler sampler;
29+ VkDescriptorPool descriptorPool;
30+ VkDescriptorSet descriptorSet;
31+ VkDescriptorSetLayout descriptorLayout;
32+
2833bool handleMessage () {
2934 SDL_Event event;
3035 while (SDL_PollEvent (&event)) {
@@ -60,17 +65,21 @@ void recreateRenderPass() {
6065}
6166
6267float vertexData[] = {
63- 0 .5f , -0 .5f ,
64- 1 .0f , 0 .0f , 0 .0f ,
68+ 0 .5f , -0 .5f , // Position
69+ 1 .0f , 0 .0f , 0 .0f , // Color
70+ 1 .0f , 0 .0f , // Texcoord
6571
6672 0 .5f , 0 .5f ,
6773 0 .0f , 1 .0f , 0 .0f ,
74+ 1 .0f , 1 .0f ,
6875
6976 -0 .5f , 0 .5f ,
7077 0 .0f , 0 .0f , 1 .0f ,
78+ 0 .0f , 1 .0f ,
7179
7280 -0 .5f , -0 .5f ,
7381 0 .0f , 1 .0f , 0 .0f ,
82+ 0 .0f , 0 .0f ,
7483};
7584
7685uint32_t indexData[] = {
@@ -99,7 +108,70 @@ void initApplication(SDL_Window* window) {
99108
100109 recreateRenderPass ();
101110
102- VkVertexInputAttributeDescription vertexAttributeDescriptions[2 ] = {};
111+ {
112+ VkSamplerCreateInfo createInfo = {VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO};
113+ createInfo.magFilter = VK_FILTER_NEAREST;
114+ createInfo.minFilter = VK_FILTER_NEAREST;
115+ createInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
116+ createInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
117+ createInfo.addressModeV = createInfo.addressModeU ;
118+ createInfo.addressModeW = createInfo.addressModeU ;
119+ createInfo.mipLodBias = 0 .0f ;
120+ createInfo.maxAnisotropy = 1 .0f ;
121+ createInfo.minLod = 0 .0f ;
122+ createInfo.maxLod = 1 .0f ;
123+ VKA (vkCreateSampler (context->device , &createInfo, 0 , &sampler));
124+ }
125+
126+ {
127+ int width, height, channels;
128+ uint8_t * data = stbi_load (" ../data/images/logo.png" , &width, &height, &channels, 4 );
129+ if (!data) {
130+ LOG_ERROR (" Could not load image data" );
131+ }
132+ createImage (context, &image, width, height, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
133+ uploadDataToImage (context, &image, data, width * height * 4 , width, height, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
134+ stbi_image_free (data);
135+ }
136+
137+ {
138+ VkDescriptorPoolSize poolSizes[] = {
139+ {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1 },
140+ };
141+ VkDescriptorPoolCreateInfo createInfo = {VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO};
142+ createInfo.maxSets = 1 ;
143+ createInfo.poolSizeCount = ARRAY_COUNT (poolSizes);
144+ createInfo.pPoolSizes = poolSizes;
145+ VKA (vkCreateDescriptorPool (context->device , &createInfo, 0 , &descriptorPool));
146+ }
147+
148+ {
149+ VkDescriptorSetLayoutBinding bindings[] = {
150+ {0 , VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1 , VK_SHADER_STAGE_FRAGMENT_BIT, 0 },
151+ };
152+ VkDescriptorSetLayoutCreateInfo createInfo = {VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO};
153+ createInfo.bindingCount = ARRAY_COUNT (bindings);
154+ createInfo.pBindings = bindings;
155+ VKA (vkCreateDescriptorSetLayout (context->device , &createInfo, 0 , &descriptorLayout));
156+
157+ VkDescriptorSetAllocateInfo allocateInfo = {VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO};
158+ allocateInfo.descriptorPool = descriptorPool;
159+ allocateInfo.descriptorSetCount = 1 ;
160+ allocateInfo.pSetLayouts = &descriptorLayout;
161+ VKA (vkAllocateDescriptorSets (context->device , &allocateInfo, &descriptorSet));
162+
163+ VkDescriptorImageInfo imageInfo = { sampler, image.view , VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL};
164+ VkWriteDescriptorSet descriptorWrites[1 ];
165+ descriptorWrites[0 ] = {VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET};
166+ descriptorWrites[0 ].dstSet = descriptorSet;
167+ descriptorWrites[0 ].dstBinding = 0 ;
168+ descriptorWrites[0 ].descriptorCount = 1 ;
169+ descriptorWrites[0 ].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
170+ descriptorWrites[0 ].pImageInfo = &imageInfo;
171+ VK (vkUpdateDescriptorSets (context->device , ARRAY_COUNT (descriptorWrites), descriptorWrites, 0 , 0 ));
172+ }
173+
174+ VkVertexInputAttributeDescription vertexAttributeDescriptions[3 ] = {};
103175 vertexAttributeDescriptions[0 ].binding = 0 ;
104176 vertexAttributeDescriptions[0 ].location = 0 ;
105177 vertexAttributeDescriptions[0 ].format = VK_FORMAT_R32G32_SFLOAT;
@@ -108,11 +180,15 @@ void initApplication(SDL_Window* window) {
108180 vertexAttributeDescriptions[1 ].location = 1 ;
109181 vertexAttributeDescriptions[1 ].format = VK_FORMAT_R32G32B32_SFLOAT;
110182 vertexAttributeDescriptions[1 ].offset = sizeof (float ) * 2 ;
183+ vertexAttributeDescriptions[2 ].binding = 0 ;
184+ vertexAttributeDescriptions[2 ].location = 2 ;
185+ vertexAttributeDescriptions[2 ].format = VK_FORMAT_R32G32_SFLOAT;
186+ vertexAttributeDescriptions[2 ].offset = sizeof (float ) * 5 ;
111187 VkVertexInputBindingDescription vertexInputBinding = {};
112188 vertexInputBinding.binding = 0 ;
113189 vertexInputBinding.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
114- vertexInputBinding.stride = sizeof (float ) * 5 ;
115- pipeline = createPipeline (context, " ../shaders/color_vert .spv" , " ../shaders/color_frag .spv" , renderPass, swapchain.width , swapchain.height , vertexAttributeDescriptions, ARRAY_COUNT (vertexAttributeDescriptions), &vertexInputBinding);
190+ vertexInputBinding.stride = sizeof (float ) * 7 ;
191+ pipeline = createPipeline (context, " ../shaders/texture_vert .spv" , " ../shaders/texture_frag .spv" , renderPass, swapchain.width , swapchain.height , vertexAttributeDescriptions, ARRAY_COUNT (vertexAttributeDescriptions), &vertexInputBinding, 1 , &descriptorLayout );
116192
117193 for (uint32_t i = 0 ; i < ARRAY_COUNT (fences); ++i) {
118194 VkFenceCreateInfo createInfo = { VK_STRUCTURE_TYPE_FENCE_CREATE_INFO };
@@ -144,17 +220,6 @@ void initApplication(SDL_Window* window) {
144220
145221 createBuffer (context, &indexBuffer, sizeof (indexData), VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
146222 uploadDataToBuffer (context, &indexBuffer, indexData, sizeof (indexData));
147-
148- {
149- int width, height, channels;
150- uint8_t * data = stbi_load (" ../data/images/logo.png" , &width, &height, &channels, 4 );
151- if (!data) {
152- LOG_ERROR (" Could not load image data" );
153- }
154- createImage (context, &image, width, height, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
155- uploadDataToImage (context, &image, data, width * height * 4 , width, height, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
156- stbi_image_free (data);
157- }
158223}
159224
160225void recreateSwapchain () {
@@ -221,6 +286,7 @@ void renderApplication() {
221286 VkDeviceSize offset = 0 ;
222287 vkCmdBindVertexBuffers (commandBuffer, 0 , 1 , &vertexBuffer.buffer , &offset);
223288 vkCmdBindIndexBuffer (commandBuffer, indexBuffer.buffer , 0 , VK_INDEX_TYPE_UINT32);
289+ vkCmdBindDescriptorSets (commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.pipelineLayout , 0 , 1 , &descriptorSet, 0 , 0 );
224290
225291 vkCmdDrawIndexed (commandBuffer, ARRAY_COUNT (indexData), 1 , 0 , 0 , 0 );
226292
@@ -260,6 +326,9 @@ void renderApplication() {
260326void shutdownApplication () {
261327 VKA (vkDeviceWaitIdle (context->device ));
262328
329+ VK (vkDestroyDescriptorPool (context->device , descriptorPool, 0 ));
330+ VK (vkDestroyDescriptorSetLayout (context->device , descriptorLayout, 0 ));
331+
263332 destroyBuffer (context, &vertexBuffer);
264333 destroyBuffer (context, &indexBuffer);
265334
@@ -276,6 +345,8 @@ void shutdownApplication() {
276345
277346 destroyPipeline (context, &pipeline);
278347
348+ vkDestroySampler (context->device , sampler, 0 );
349+
279350 for (uint32_t i = 0 ; i < framebuffers.size (); ++i) {
280351 VK (vkDestroyFramebuffer (context->device , framebuffers[i], 0 ));
281352 }
0 commit comments