Get textures working (almost)

This commit is contained in:
Bailey Harrison 2023-03-21 23:52:52 +00:00
parent 9f88131371
commit 25ee640c41
6 changed files with 176 additions and 17 deletions

View File

@ -28,12 +28,16 @@ namespace engine {
struct RenderData {
std::unique_ptr<GFXDevice> gfxdev;
gfx::DrawBuffer* drawBuffer = nullptr;
/* uniforms for engine globals */
const gfx::DescriptorSetLayout* setZeroLayout;
const gfx::DescriptorSet* setZero;
struct SetZeroBuffer {
glm::mat4 proj;
};
const gfx::Image* myImage = nullptr;
const gfx::Sampler* mySampler = nullptr;
gfx::UniformBuffer* setZeroBuffer;
/* uniforms for per-frame data */
const gfx::DescriptorSetLayout* setOneLayout;

View File

@ -17,6 +17,7 @@ namespace engine::gfx {
struct DescriptorSetLayout;
struct DescriptorSet;
struct Image;
struct Sampler;
enum class MSAALevel {
MSAA_OFF,

View File

@ -38,7 +38,7 @@ namespace engine {
gfx::DescriptorSet* allocateDescriptorSet(const gfx::DescriptorSetLayout* layout);
// This updates all copies of the descriptor. This cannot be used after any frames have been renderered
void updateDescriptorUniformBuffer(const gfx::DescriptorSet* set, uint32_t binding, const gfx::UniformBuffer* buffer, size_t offset, size_t range);
void updateDescriptorCombinedImageSampler(const gfx::DescriptorSet* set, uint32_t binding);
void updateDescriptorCombinedImageSampler(const gfx::DescriptorSet* set, uint32_t binding, const gfx::Image* image, const gfx::Sampler* sampler);
gfx::UniformBuffer* createUniformBuffer(uint64_t size, const void* initialData);
void destroyUniformBuffer(const gfx::UniformBuffer* descriptorBuffer);
@ -50,6 +50,10 @@ namespace engine {
void destroyBuffer(const gfx::Buffer* buffer);
gfx::Image* createImage(uint32_t w, uint32_t h, const void* imageData);
void destroyImage(const gfx::Image* image);
gfx::Sampler* createSampler();
void destroySampler(const gfx::Sampler* sampler);
gfx::Texture* createTexture(
const void* imageData,

View File

@ -7,7 +7,7 @@ layout(location = 3) in vec3 fragLightPos;
layout(location = 0) out vec4 outColor;
//layout(set = 1, binding = 0) uniform sampler2D texSampler;
layout(set = 0, binding = 1) uniform sampler2D texSampler;
void main() {
@ -15,8 +15,7 @@ void main() {
vec3 lightColor = vec3(1.0, 1.0, 1.0);
vec3 ambientColor = vec3(1.0, 1.0, 1.0);
float ambientStrength = 0.05;
//vec3 baseColor = vec3(texture(texSampler, fragUV));
vec3 baseColor = vec3(mod(fragUV.x, 1.0), mod(fragUV.y, 1.0), 0.0);
vec3 baseColor = vec3(texture(texSampler, fragUV));
vec3 emission = vec3(0.0, 0.0, 0.0);
// code

View File

@ -76,22 +76,33 @@ namespace engine {
// initialise the render data
renderData.gfxdev = std::make_unique<GFXDevice>(appName, appVersion, m_window->getHandle(), graphicsSettings);
std::vector<gfx::DescriptorSetLayoutBinding> layoutBindings;
std::vector<gfx::DescriptorSetLayoutBinding> setZeroLayoutBindings;
{
auto& binding0 = layoutBindings.emplace_back();
auto& binding0 = setZeroLayoutBindings.emplace_back();
binding0.descriptorType = gfx::DescriptorType::UNIFORM_BUFFER;
binding0.stageFlags = gfx::ShaderStageFlags::VERTEX;
auto& binding1 = setZeroLayoutBindings.emplace_back();
binding1.descriptorType = gfx::DescriptorType::COMBINED_IMAGE_SAMPLER;
binding1.stageFlags = gfx::ShaderStageFlags::FRAGMENT;
}
renderData.setZeroLayout = gfx()->createDescriptorSetLayout(layoutBindings);
renderData.setZeroLayout = gfx()->createDescriptorSetLayout(setZeroLayoutBindings);
renderData.setZero = gfx()->allocateDescriptorSet(renderData.setZeroLayout);
RenderData::SetZeroBuffer initialSetZeroData{
.proj = glm::perspectiveZO(glm::radians(70.0f), 1024.0f / 768.0f, 0.1f, 1000.0f),
};
renderData.setZeroBuffer = gfx()->createUniformBuffer(sizeof(RenderData::SetZeroBuffer), &initialSetZeroData);
gfx()->updateDescriptorUniformBuffer(renderData.setZero, 0, renderData.setZeroBuffer, 0, sizeof(RenderData::SetZeroBuffer));
renderData.myImage = gfx()->createImage(512, 512, nullptr);
renderData.mySampler = gfx()->createSampler();
gfx()->updateDescriptorCombinedImageSampler(renderData.setZero, 1, renderData.myImage, renderData.mySampler);
renderData.setOneLayout = gfx()->createDescriptorSetLayout(layoutBindings);
std::vector<gfx::DescriptorSetLayoutBinding> setOneLayoutBindings;
{
auto& binding0 = setOneLayoutBindings.emplace_back();
binding0.descriptorType = gfx::DescriptorType::UNIFORM_BUFFER;
binding0.stageFlags = gfx::ShaderStageFlags::VERTEX;
}
renderData.setOneLayout = gfx()->createDescriptorSetLayout(setOneLayoutBindings);
renderData.setOne = gfx()->allocateDescriptorSet(renderData.setOneLayout);
RenderData::SetOneBuffer initialSetOneData{
.view = glm::mat4{ 1.0f },
@ -144,6 +155,9 @@ namespace engine {
{
gfx()->destroyUniformBuffer(renderData.setOneBuffer);
gfx()->destroyDescriptorSetLayout(renderData.setOneLayout);
gfx()->destroySampler(renderData.mySampler);
gfx()->destroyImage(renderData.myImage);
gfx()->destroyUniformBuffer(renderData.setZeroBuffer);
gfx()->destroyDescriptorSetLayout(renderData.setZeroLayout);
}

View File

@ -94,6 +94,16 @@ namespace engine {
VkPipeline handle = VK_NULL_HANDLE;
};
struct gfx::Image {
VkImage image = VK_NULL_HANDLE;
VkImageView view = VK_NULL_HANDLE;
VmaAllocation allocation = VK_NULL_HANDLE;
};
struct gfx::Sampler {
VkSampler sampler = VK_NULL_HANDLE;
};
struct gfx::Texture {
};
@ -362,7 +372,9 @@ namespace engine {
.format = VK_FORMAT_R8G8B8A8_SRGB,
.properties = VkFormatProperties{
.linearTilingFeatures = {},
.optimalTilingFeatures = VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT,
.optimalTilingFeatures =
VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT |
VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT,
.bufferFeatures = {},
}
}
@ -1084,13 +1096,13 @@ namespace engine {
}
}
void GFXDevice::updateDescriptorCombinedImageSampler(const gfx::DescriptorSet *set, uint32_t binding)
void GFXDevice::updateDescriptorCombinedImageSampler(const gfx::DescriptorSet *set, uint32_t binding, const gfx::Image* image, const gfx::Sampler* sampler)
{
assert(pimpl->FRAMECOUNT == 0);
VkDescriptorImageInfo imageInfo{};
imageInfo.sampler = VK_NULL_HANDLE;
imageInfo.imageView = VK_NULL_HANDLE;
imageInfo.sampler = sampler->sampler;
imageInfo.imageView = image->view;
imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
for (uint32_t i = 0; i < FRAMES_IN_FLIGHT; i++) {
@ -1259,13 +1271,138 @@ namespace engine {
gfx::Image* GFXDevice::createImage(uint32_t w, uint32_t h, const void* imageData)
{
(void)w;
(void)h;
(void)imageData;
return nullptr;
assert(pimpl->FRAMECOUNT == 0);
gfx::Image* out = new gfx::Image{};
VkImageCreateInfo imageInfo{};
imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
imageInfo.flags = 0;
imageInfo.imageType = VK_IMAGE_TYPE_2D;
imageInfo.format = VK_FORMAT_R8G8B8A8_SRGB;
imageInfo.extent.width = w;
imageInfo.extent.height = h;
imageInfo.extent.depth = 1;
imageInfo.mipLevels = 1;
imageInfo.arrayLayers = 1;
imageInfo.samples = VK_SAMPLE_COUNT_1_BIT;
imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
imageInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT;
imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
imageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
VmaAllocationCreateInfo allocCreateInfo{};
allocCreateInfo.flags = 0;
allocCreateInfo.usage = VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE;
allocCreateInfo.priority = 0.5f;
VKCHECK(vmaCreateImage(pimpl->allocator, &imageInfo, &allocCreateInfo, &out->image, &out->allocation, nullptr));
VkImageViewCreateInfo viewInfo{};
viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
viewInfo.image = out->image;
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
viewInfo.format = imageInfo.format;
viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
viewInfo.subresourceRange.baseMipLevel = 0;
viewInfo.subresourceRange.levelCount = 1;
viewInfo.subresourceRange.baseArrayLayer = 0;
viewInfo.subresourceRange.layerCount = 1;
VKCHECK(vkCreateImageView(pimpl->device.device, &viewInfo, nullptr, &out->view));
// Do a pipeline barrier to transition the layout
VkCommandBufferAllocateInfo allocInfo{};
allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
allocInfo.commandPool = pimpl->transferCommandPool;
allocInfo.commandBufferCount = 1;
VkCommandBuffer commandBuffer;
VKCHECK(vkAllocateCommandBuffers(pimpl->device.device, &allocInfo, &commandBuffer));
{ // record the command buffer
VkCommandBufferBeginInfo beginInfo{};
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
VKCHECK(vkBeginCommandBuffer(commandBuffer, &beginInfo));
VkImageMemoryBarrier2 barrier{};
barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2;
barrier.srcStageMask = VK_PIPELINE_STAGE_2_NONE;
barrier.srcAccessMask = VK_ACCESS_2_NONE;
barrier.dstStageMask = VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT;
barrier.dstAccessMask = VK_ACCESS_2_SHADER_SAMPLED_READ_BIT;
barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
barrier.srcQueueFamilyIndex = pimpl->device.queues.transferQueueFamily;
barrier.dstQueueFamilyIndex = pimpl->device.queues.presentAndDrawQueueFamily;
barrier.image = out->image;
barrier.subresourceRange = viewInfo.subresourceRange;
VkDependencyInfo depInfo{};
depInfo.sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO;
depInfo.imageMemoryBarrierCount = 1;
depInfo.pImageMemoryBarriers = &barrier;
vkCmdPipelineBarrier2(commandBuffer, &depInfo);
VKCHECK(vkEndCommandBuffer(commandBuffer));
}
// submit
VkSubmitInfo submitInfo{};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &commandBuffer;
VKCHECK(vkQueueSubmit(pimpl->device.queues.transferQueues[0], 1, &submitInfo, VK_NULL_HANDLE));
VKCHECK(vkQueueWaitIdle(pimpl->device.queues.transferQueues[0]));
vkFreeCommandBuffers(pimpl->device.device, pimpl->transferCommandPool, 1, &commandBuffer);
return out;
}
gfx::Texture* GFXDevice::createTexture(
void GFXDevice::destroyImage(const gfx::Image *image)
{
vkDestroyImageView(pimpl->device.device, image->view, nullptr);
vmaDestroyImage(pimpl->allocator, image->image, image->allocation);
delete image;
}
gfx::Sampler *GFXDevice::createSampler()
{
gfx::Sampler* out = new gfx::Sampler{};
VkSamplerCreateInfo samplerInfo{};
samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
samplerInfo.magFilter = VK_FILTER_NEAREST;
samplerInfo.minFilter = VK_FILTER_NEAREST;
samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST;
samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT;
samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT;
samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT;
samplerInfo.mipLodBias = 0.0f; // wtf
samplerInfo.anisotropyEnable = VK_FALSE;
samplerInfo.minLod = 0.0f;
samplerInfo.maxLod = 0.0f;
VKCHECK(vkCreateSampler(pimpl->device.device, &samplerInfo, nullptr, &out->sampler));
return out;
}
void GFXDevice::destroySampler(const gfx::Sampler *sampler)
{
vkDestroySampler(pimpl->device.device, sampler->sampler, nullptr);
delete sampler;
}
gfx::Texture* GFXDevice::createTexture(
const void* imageData,
uint32_t width,
uint32_t height,