mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-04-17 17:43:52 +00:00
fix(rendering): water reflection render pass compat, anisotropy feature, shadow pool race
Three bugs found via AMD RADV crash log: 1. Water reflection render pass used BOTTOM_OF_PIPE as srcStageMask but pipelines were created against the main pass (EARLY_FRAGMENT_TESTS | COLOR_ATTACHMENT_OUTPUT). AMD enforces strict render pass compatibility → SIGSEGV when scene renders into reflection texture. 2. samplerAnisotropy was never enabled during device creation despite being used in sampler creation — now requested via PhysicalDeviceSelector. 3. Shadow texture descriptor pool was reset each frame while prior frame's command buffers might still reference it. Split into per-frame-slot pools so each reset is fence-guarded.
This commit is contained in:
parent
62b8a757a3
commit
4f7912cf45
4 changed files with 20 additions and 12 deletions
|
|
@ -391,8 +391,9 @@ private:
|
||||||
VkDescriptorSet shadowParamsSet_ = VK_NULL_HANDLE;
|
VkDescriptorSet shadowParamsSet_ = VK_NULL_HANDLE;
|
||||||
::VkBuffer shadowParamsUBO_ = VK_NULL_HANDLE;
|
::VkBuffer shadowParamsUBO_ = VK_NULL_HANDLE;
|
||||||
VmaAllocation shadowParamsAlloc_ = VK_NULL_HANDLE;
|
VmaAllocation shadowParamsAlloc_ = VK_NULL_HANDLE;
|
||||||
// Per-frame pool for foliage shadow texture descriptor sets
|
// Per-frame pools for foliage shadow texture descriptor sets (one per frame-in-flight)
|
||||||
VkDescriptorPool shadowTexPool_ = VK_NULL_HANDLE;
|
static constexpr uint32_t kShadowTexPoolFrames = 2;
|
||||||
|
VkDescriptorPool shadowTexPool_[kShadowTexPoolFrames] = {};
|
||||||
|
|
||||||
// Particle pipelines
|
// Particle pipelines
|
||||||
VkPipeline particlePipeline_ = VK_NULL_HANDLE; // M2 emitter particles
|
VkPipeline particlePipeline_ = VK_NULL_HANDLE; // M2 emitter particles
|
||||||
|
|
|
||||||
|
|
@ -814,7 +814,7 @@ void M2Renderer::shutdown() {
|
||||||
// Destroy shadow resources
|
// Destroy shadow resources
|
||||||
destroyPipeline(shadowPipeline_);
|
destroyPipeline(shadowPipeline_);
|
||||||
if (shadowPipelineLayout_) { vkDestroyPipelineLayout(device, shadowPipelineLayout_, nullptr); shadowPipelineLayout_ = VK_NULL_HANDLE; }
|
if (shadowPipelineLayout_) { vkDestroyPipelineLayout(device, shadowPipelineLayout_, nullptr); shadowPipelineLayout_ = VK_NULL_HANDLE; }
|
||||||
if (shadowTexPool_) { vkDestroyDescriptorPool(device, shadowTexPool_, nullptr); shadowTexPool_ = VK_NULL_HANDLE; }
|
for (auto& pool : shadowTexPool_) { if (pool) { vkDestroyDescriptorPool(device, pool, nullptr); pool = VK_NULL_HANDLE; } }
|
||||||
if (shadowParamsPool_) { vkDestroyDescriptorPool(device, shadowParamsPool_, nullptr); shadowParamsPool_ = VK_NULL_HANDLE; }
|
if (shadowParamsPool_) { vkDestroyDescriptorPool(device, shadowParamsPool_, nullptr); shadowParamsPool_ = VK_NULL_HANDLE; }
|
||||||
if (shadowParamsLayout_) { vkDestroyDescriptorSetLayout(device, shadowParamsLayout_, nullptr); shadowParamsLayout_ = VK_NULL_HANDLE; }
|
if (shadowParamsLayout_) { vkDestroyDescriptorSetLayout(device, shadowParamsLayout_, nullptr); shadowParamsLayout_ = VK_NULL_HANDLE; }
|
||||||
if (shadowParamsUBO_) { vmaDestroyBuffer(alloc, shadowParamsUBO_, shadowParamsAlloc_); shadowParamsUBO_ = VK_NULL_HANDLE; }
|
if (shadowParamsUBO_) { vmaDestroyBuffer(alloc, shadowParamsUBO_, shadowParamsAlloc_); shadowParamsUBO_ = VK_NULL_HANDLE; }
|
||||||
|
|
@ -2939,7 +2939,7 @@ bool M2Renderer::initializeShadow(VkRenderPass shadowRenderPass) {
|
||||||
writes[1].pBufferInfo = &bufInfo;
|
writes[1].pBufferInfo = &bufInfo;
|
||||||
vkUpdateDescriptorSets(device, 2, writes, 0, nullptr);
|
vkUpdateDescriptorSets(device, 2, writes, 0, nullptr);
|
||||||
|
|
||||||
// Per-frame pool for foliage shadow texture sets (reset each frame)
|
// Per-frame pools for foliage shadow texture sets (one per frame-in-flight, reset each frame)
|
||||||
{
|
{
|
||||||
VkDescriptorPoolSize texPoolSizes[2]{};
|
VkDescriptorPoolSize texPoolSizes[2]{};
|
||||||
texPoolSizes[0].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
texPoolSizes[0].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||||
|
|
@ -2951,9 +2951,11 @@ bool M2Renderer::initializeShadow(VkRenderPass shadowRenderPass) {
|
||||||
texPoolCI.maxSets = 256;
|
texPoolCI.maxSets = 256;
|
||||||
texPoolCI.poolSizeCount = 2;
|
texPoolCI.poolSizeCount = 2;
|
||||||
texPoolCI.pPoolSizes = texPoolSizes;
|
texPoolCI.pPoolSizes = texPoolSizes;
|
||||||
if (vkCreateDescriptorPool(device, &texPoolCI, nullptr, &shadowTexPool_) != VK_SUCCESS) {
|
for (uint32_t f = 0; f < kShadowTexPoolFrames; ++f) {
|
||||||
LOG_ERROR("M2Renderer: failed to create shadow texture pool");
|
if (vkCreateDescriptorPool(device, &texPoolCI, nullptr, &shadowTexPool_[f]) != VK_SUCCESS) {
|
||||||
return false;
|
LOG_ERROR("M2Renderer: failed to create shadow texture pool ", f);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3029,9 +3031,11 @@ void M2Renderer::renderShadow(VkCommandBuffer cmd, const glm::mat4& lightSpaceMa
|
||||||
|
|
||||||
const float shadowRadiusSq = shadowRadius * shadowRadius;
|
const float shadowRadiusSq = shadowRadius * shadowRadius;
|
||||||
|
|
||||||
// Reset per-frame texture descriptor pool for foliage alpha-test sets
|
// Reset this frame slot's texture descriptor pool (safe: fence was waited on in beginFrame)
|
||||||
if (shadowTexPool_) {
|
const uint32_t frameIdx = vkCtx_->getCurrentFrame();
|
||||||
vkResetDescriptorPool(vkCtx_->getDevice(), shadowTexPool_, 0);
|
VkDescriptorPool curShadowTexPool = shadowTexPool_[frameIdx];
|
||||||
|
if (curShadowTexPool) {
|
||||||
|
vkResetDescriptorPool(vkCtx_->getDevice(), curShadowTexPool, 0);
|
||||||
}
|
}
|
||||||
// Cache: texture imageView -> allocated descriptor set (avoids duplicates within frame)
|
// Cache: texture imageView -> allocated descriptor set (avoids duplicates within frame)
|
||||||
// Reuse persistent map — pool reset already invalidated the sets.
|
// Reuse persistent map — pool reset already invalidated the sets.
|
||||||
|
|
@ -3046,7 +3050,7 @@ void M2Renderer::renderShadow(VkCommandBuffer cmd, const glm::mat4& lightSpaceMa
|
||||||
VkDescriptorSet set = VK_NULL_HANDLE;
|
VkDescriptorSet set = VK_NULL_HANDLE;
|
||||||
VkDescriptorSetAllocateInfo ai{};
|
VkDescriptorSetAllocateInfo ai{};
|
||||||
ai.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
|
ai.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
|
||||||
ai.descriptorPool = shadowTexPool_;
|
ai.descriptorPool = curShadowTexPool;
|
||||||
ai.descriptorSetCount = 1;
|
ai.descriptorSetCount = 1;
|
||||||
ai.pSetLayouts = &shadowParamsLayout_;
|
ai.pSetLayouts = &shadowParamsLayout_;
|
||||||
if (vkAllocateDescriptorSets(vkCtx_->getDevice(), &ai, &set) != VK_SUCCESS) {
|
if (vkAllocateDescriptorSets(vkCtx_->getDevice(), &ai, &set) != VK_SUCCESS) {
|
||||||
|
|
|
||||||
|
|
@ -279,8 +279,11 @@ bool VkContext::createSurface(SDL_Window* window) {
|
||||||
|
|
||||||
bool VkContext::selectPhysicalDevice() {
|
bool VkContext::selectPhysicalDevice() {
|
||||||
vkb::PhysicalDeviceSelector selector{vkbInstance_};
|
vkb::PhysicalDeviceSelector selector{vkbInstance_};
|
||||||
|
VkPhysicalDeviceFeatures requiredFeatures{};
|
||||||
|
requiredFeatures.samplerAnisotropy = VK_TRUE;
|
||||||
selector.set_surface(surface)
|
selector.set_surface(surface)
|
||||||
.set_minimum_version(1, 1)
|
.set_minimum_version(1, 1)
|
||||||
|
.set_required_features(requiredFeatures)
|
||||||
.prefer_gpu_device_type(vkb::PreferredDeviceType::discrete);
|
.prefer_gpu_device_type(vkb::PreferredDeviceType::discrete);
|
||||||
|
|
||||||
auto physRet = selector.select();
|
auto physRet = selector.select();
|
||||||
|
|
|
||||||
|
|
@ -1784,7 +1784,7 @@ void WaterRenderer::createReflectionResources() {
|
||||||
VkSubpassDependency dep{};
|
VkSubpassDependency dep{};
|
||||||
dep.srcSubpass = VK_SUBPASS_EXTERNAL;
|
dep.srcSubpass = VK_SUBPASS_EXTERNAL;
|
||||||
dep.dstSubpass = 0;
|
dep.dstSubpass = 0;
|
||||||
dep.srcStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
|
dep.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;
|
||||||
dep.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;
|
dep.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;
|
||||||
dep.srcAccessMask = 0;
|
dep.srcAccessMask = 0;
|
||||||
dep.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
|
dep.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue