diff --git a/Editor/MeshWindow.cpp b/Editor/MeshWindow.cpp index f6bf411c6..6dc7a23dc 100644 --- a/Editor/MeshWindow.cpp +++ b/Editor/MeshWindow.cpp @@ -34,7 +34,7 @@ void MeshWindow::Create(EditorComponent* _editor) float step = hei + 2; float wid = 170; - float infolabel_height = 190; + float infolabel_height = 200; meshInfoLabel.Create("Mesh Info"); meshInfoLabel.SetPos(XMFLOAT2(20, y)); meshInfoLabel.SetSize(XMFLOAT2(260, infolabel_height)); @@ -717,6 +717,7 @@ void MeshWindow::SetEntity(Entity entity, int subset) ss += "Mesh name: " + name.name + "\n"; ss += "Vertex count: " + std::to_string(mesh->vertex_positions.size()) + "\n"; ss += "Index count: " + std::to_string(mesh->indices.size()) + "\n"; + ss += "Index format: " + std::string(wi::graphics::GetIndexBufferFormatString(mesh->GetIndexFormat())) + "\n"; ss += "Subset count: " + std::to_string(mesh->subsets.size()) + " (" + std::to_string(mesh->GetLODCount()) + " LODs)\n"; ss += "GPU memory: " + std::to_string((mesh->generalBuffer.GetDesc().size + mesh->streamoutBuffer.GetDesc().size) / 1024.0f / 1024.0f) + " MB\n"; ss += "\nVertex buffers:\n"; diff --git a/WickedEngine/shaders/impostor_prepareCS.hlsl b/WickedEngine/shaders/impostor_prepareCS.hlsl index c1f68b4d6..2ba409a17 100644 --- a/WickedEngine/shaders/impostor_prepareCS.hlsl +++ b/WickedEngine/shaders/impostor_prepareCS.hlsl @@ -2,7 +2,8 @@ static const uint THREADCOUNT = 64; -static const float3 BILLBOARD[] = { +static const float3 BILLBOARD[] = +{ float3(-1, -1, 0), float3(1, -1, 0), float3(-1, 1, 0), @@ -12,7 +13,7 @@ static const float3 BILLBOARD[] = { RWBuffer output_indices : register(u0); RWByteAddressBuffer output_vertices_pos_nor : register(u1); RWByteAddressBuffer output_impostor_data : register(u2); -RWByteAddressBuffer output_indirect : register(u3); +RWStructuredBuffer output_indirect : register(u3); struct ObjectCount { @@ -46,7 +47,7 @@ void main(uint3 DTid : SV_DispatchThreadID) uint waveOffset; if (WaveIsFirstLane() && waveAppendCount > 0) { - output_indirect.InterlockedAdd(0, waveAppendCount * 6u, waveOffset); // atomic into IndexCountPerInstance + InterlockedAdd(output_indirect[0].IndexCountPerInstance, waveAppendCount * 6u, waveOffset); } waveOffset = WaveReadLaneFirst(waveOffset); diff --git a/WickedEngine/wiGraphics.h b/WickedEngine/wiGraphics.h index 012935332..8e05fd9bd 100644 --- a/WickedEngine/wiGraphics.h +++ b/WickedEngine/wiGraphics.h @@ -1664,6 +1664,25 @@ namespace wi::graphics return IndexBufferFormat::UINT16; } } + constexpr IndexBufferFormat GetIndexBufferFormat(uint32_t vertex_count) + { + return vertex_count > 65536 ? IndexBufferFormat::UINT32 : IndexBufferFormat::UINT16; + } + constexpr Format GetIndexBufferFormatRaw(uint32_t vertex_count) + { + return vertex_count > 65536 ? Format::R32_UINT : Format::R16_UINT; + } + constexpr const char* GetIndexBufferFormatString(IndexBufferFormat format) + { + switch (format) + { + default: + case IndexBufferFormat::UINT32: + return "UINT32"; + case IndexBufferFormat::UINT16: + return "UINT16"; + } + } constexpr uint32_t AlignTo(uint32_t value, uint32_t alignment) { diff --git a/WickedEngine/wiGraphicsDevice.h b/WickedEngine/wiGraphicsDevice.h index 8a459353b..d20d87537 100644 --- a/WickedEngine/wiGraphicsDevice.h +++ b/WickedEngine/wiGraphicsDevice.h @@ -84,7 +84,7 @@ namespace wi::graphics virtual bool CreateVideoDecoder(const VideoDesc* desc, VideoDecoder* video_decoder) const { return false; }; virtual int CreateSubresource(Texture* texture, SubresourceType type, uint32_t firstSlice, uint32_t sliceCount, uint32_t firstMip, uint32_t mipCount, const Format* format_change = nullptr, const ImageAspect* aspect = nullptr, const Swizzle* swizzle = nullptr) const = 0; - virtual int CreateSubresource(GPUBuffer* buffer, SubresourceType type, uint64_t offset, uint64_t size = ~0, const Format* format_change = nullptr) const = 0; + virtual int CreateSubresource(GPUBuffer* buffer, SubresourceType type, uint64_t offset, uint64_t size = ~0, const Format* format_change = nullptr, const uint32_t* structuredbuffer_stride_change = nullptr) const = 0; virtual int GetDescriptorIndex(const GPUResource* resource, SubresourceType type, int subresource = -1) const = 0; virtual int GetDescriptorIndex(const Sampler* sampler) const = 0; diff --git a/WickedEngine/wiGraphicsDevice_DX12.cpp b/WickedEngine/wiGraphicsDevice_DX12.cpp index f0348b2e7..3c71c23ab 100644 --- a/WickedEngine/wiGraphicsDevice_DX12.cpp +++ b/WickedEngine/wiGraphicsDevice_DX12.cpp @@ -4917,7 +4917,7 @@ using namespace dx12_internal; } return -1; } - int GraphicsDevice_DX12::CreateSubresource(GPUBuffer* buffer, SubresourceType type, uint64_t offset, uint64_t size, const Format* format_change) const + int GraphicsDevice_DX12::CreateSubresource(GPUBuffer* buffer, SubresourceType type, uint64_t offset, uint64_t size, const Format* format_change, const uint32_t* structuredbuffer_stride_change) const { auto internal_state = to_internal(buffer); const GPUBufferDesc& desc = buffer->GetDesc(); @@ -4952,14 +4952,19 @@ using namespace dx12_internal; srv_desc.Buffer.Flags = D3D12_BUFFER_SRV_FLAG_RAW; srv_desc.Buffer.NumElements = (UINT)std::min(size, desc.size - offset) / sizeof(uint32_t); } - else if (has_flag(desc.misc_flags, ResourceMiscFlag::BUFFER_STRUCTURED)) + else if (has_flag(desc.misc_flags, ResourceMiscFlag::BUFFER_STRUCTURED) || (structuredbuffer_stride_change != nullptr)) { // This is a Structured Buffer + uint32_t stride = desc.stride; + if (structuredbuffer_stride_change != nullptr) + { + stride = *structuredbuffer_stride_change; + } srv_desc.Format = DXGI_FORMAT_UNKNOWN; srv_desc.ViewDimension = D3D12_SRV_DIMENSION_BUFFER; - srv_desc.Buffer.FirstElement = (UINT)offset / desc.stride; - srv_desc.Buffer.NumElements = (UINT)std::min(size, desc.size - offset) / desc.stride; - srv_desc.Buffer.StructureByteStride = desc.stride; + srv_desc.Buffer.FirstElement = (UINT)offset / stride; + srv_desc.Buffer.NumElements = (UINT)std::min(size, desc.size - offset) / stride; + srv_desc.Buffer.StructureByteStride = stride; } } else @@ -5000,13 +5005,18 @@ using namespace dx12_internal; uav_desc.Buffer.FirstElement = (UINT)offset / sizeof(uint32_t); uav_desc.Buffer.NumElements = (UINT)std::min(size, desc.size - offset) / sizeof(uint32_t); } - else if (has_flag(desc.misc_flags, ResourceMiscFlag::BUFFER_STRUCTURED)) + else if (has_flag(desc.misc_flags, ResourceMiscFlag::BUFFER_STRUCTURED) || (structuredbuffer_stride_change != nullptr)) { // This is a Structured Buffer + uint32_t stride = desc.stride; + if (structuredbuffer_stride_change != nullptr) + { + stride = *structuredbuffer_stride_change; + } uav_desc.Format = DXGI_FORMAT_UNKNOWN; - uav_desc.Buffer.FirstElement = (UINT)offset / desc.stride; - uav_desc.Buffer.NumElements = (UINT)std::min(size, desc.size - offset) / desc.stride; - uav_desc.Buffer.StructureByteStride = desc.stride; + uav_desc.Buffer.FirstElement = (UINT)offset / stride; + uav_desc.Buffer.NumElements = (UINT)std::min(size, desc.size - offset) / stride; + uav_desc.Buffer.StructureByteStride = stride; } } else diff --git a/WickedEngine/wiGraphicsDevice_DX12.h b/WickedEngine/wiGraphicsDevice_DX12.h index 516e457d0..29e7d7ee0 100644 --- a/WickedEngine/wiGraphicsDevice_DX12.h +++ b/WickedEngine/wiGraphicsDevice_DX12.h @@ -239,7 +239,7 @@ namespace wi::graphics bool CreateVideoDecoder(const VideoDesc* desc, VideoDecoder* video_decoder) const override; int CreateSubresource(Texture* texture, SubresourceType type, uint32_t firstSlice, uint32_t sliceCount, uint32_t firstMip, uint32_t mipCount, const Format* format_change = nullptr, const ImageAspect* aspect = nullptr, const Swizzle* swizzle = nullptr) const override; - int CreateSubresource(GPUBuffer* buffer, SubresourceType type, uint64_t offset, uint64_t size = ~0, const Format* format_change = nullptr) const override; + int CreateSubresource(GPUBuffer* buffer, SubresourceType type, uint64_t offset, uint64_t size = ~0, const Format* format_change = nullptr, const uint32_t* structuredbuffer_stride_change = nullptr) const override; int GetDescriptorIndex(const GPUResource* resource, SubresourceType type, int subresource = -1) const override; int GetDescriptorIndex(const Sampler* sampler) const override; diff --git a/WickedEngine/wiGraphicsDevice_Vulkan.cpp b/WickedEngine/wiGraphicsDevice_Vulkan.cpp index 27bd467c7..62de0e343 100644 --- a/WickedEngine/wiGraphicsDevice_Vulkan.cpp +++ b/WickedEngine/wiGraphicsDevice_Vulkan.cpp @@ -6528,7 +6528,7 @@ using namespace vulkan_internal; } return -1; } - int GraphicsDevice_Vulkan::CreateSubresource(GPUBuffer* buffer, SubresourceType type, uint64_t offset, uint64_t size, const Format* format_change) const + int GraphicsDevice_Vulkan::CreateSubresource(GPUBuffer* buffer, SubresourceType type, uint64_t offset, uint64_t size, const Format* format_change, const uint32_t* structuredbuffer_stride_change) const { auto internal_state = to_internal(buffer); const GPUBufferDesc& desc = buffer->GetDesc(); diff --git a/WickedEngine/wiGraphicsDevice_Vulkan.h b/WickedEngine/wiGraphicsDevice_Vulkan.h index 01299e23c..0a20e6114 100644 --- a/WickedEngine/wiGraphicsDevice_Vulkan.h +++ b/WickedEngine/wiGraphicsDevice_Vulkan.h @@ -299,7 +299,7 @@ namespace wi::graphics bool CreateVideoDecoder(const VideoDesc* desc, VideoDecoder* video_decoder) const override; int CreateSubresource(Texture* texture, SubresourceType type, uint32_t firstSlice, uint32_t sliceCount, uint32_t firstMip, uint32_t mipCount, const Format* format_change = nullptr, const ImageAspect* aspect = nullptr, const Swizzle* swizzle = nullptr) const override; - int CreateSubresource(GPUBuffer* buffer, SubresourceType type, uint64_t offset, uint64_t size = ~0, const Format* format_change = nullptr) const override; + int CreateSubresource(GPUBuffer* buffer, SubresourceType type, uint64_t offset, uint64_t size = ~0, const Format* format_change = nullptr, const uint32_t* structuredbuffer_stride_change = nullptr) const override; int GetDescriptorIndex(const GPUResource* resource, SubresourceType type, int subresource = -1) const override; int GetDescriptorIndex(const Sampler* sampler) const override; diff --git a/WickedEngine/wiHairParticle.cpp b/WickedEngine/wiHairParticle.cpp index 9b95a5547..78f8a855e 100644 --- a/WickedEngine/wiHairParticle.cpp +++ b/WickedEngine/wiHairParticle.cpp @@ -32,18 +32,13 @@ namespace wi uint64_t HairParticleSystem::GetMemorySizeInBytes() const { - if (!simulationBuffer.IsValid()) + if (!generalBuffer.IsValid()) return 0; uint64_t retVal = 0; - retVal += simulationBuffer.GetDesc().size; retVal += constantBuffer.GetDesc().size; - retVal += vertexBuffer_POS[0].GetDesc().size; - retVal += vertexBuffer_POS[1].GetDesc().size; - retVal += vertexBuffer_UVS.GetDesc().size; - retVal += culledIndexBuffer.GetDesc().size; - retVal += indirectBuffer.GetDesc().size; + retVal += generalBuffer.GetDesc().size; retVal += indexBuffer.GetDesc().size; retVal += vertexBuffer_length.GetDesc().size; @@ -96,36 +91,78 @@ namespace wi const uint32_t particleCount = GetParticleCount(); if (particleCount > 0) { - bd.stride = sizeof(PatchSimulationData); - bd.size = bd.stride * particleCount; - device->CreateBuffer(&bd, nullptr, &simulationBuffer); - device->SetName(&simulationBuffer, "HairParticleSystem::simulationBuffer"); + const Format ib_format = GetIndexBufferFormatRaw(particleCount * 4); - bd.misc_flags = ResourceMiscFlag::BUFFER_RAW; + simulation_view.size = sizeof(PatchSimulationData) * particleCount; + vb_pos[0].size = sizeof(MeshComponent::Vertex_POS) * 4 * particleCount; + vb_pos[1].size = sizeof(MeshComponent::Vertex_POS) * 4 * particleCount; + vb_uvs.size = sizeof(MeshComponent::Vertex_UVS) * 4 * particleCount; + ib_culled.size = GetFormatStride(ib_format) * 6 * particleCount; + indirect_view.size = sizeof(IndirectDrawArgsIndexedInstanced); + + bd.bind_flags = BindFlag::SHADER_RESOURCE | BindFlag::UNORDERED_ACCESS | BindFlag::INDEX_BUFFER; + bd.misc_flags = ResourceMiscFlag::BUFFER_RAW | ResourceMiscFlag::INDIRECT_ARGS; if (device->CheckCapability(GraphicsDeviceCapability::RAYTRACING)) { bd.misc_flags |= ResourceMiscFlag::RAY_TRACING; } - bd.stride = sizeof(MeshComponent::Vertex_POS); - bd.size = bd.stride * 4 * particleCount; - device->CreateBuffer(&bd, nullptr, &vertexBuffer_POS[0]); - device->SetName(&vertexBuffer_POS[0], "HairParticleSystem::vertexBuffer_POS[0]"); - device->CreateBuffer(&bd, nullptr, &vertexBuffer_POS[1]); - device->SetName(&vertexBuffer_POS[1], "HairParticleSystem::vertexBuffer_POS[1]"); + bd.size = + simulation_view.size + + vb_pos[0].size + + vb_pos[1].size + + vb_uvs.size + + ib_culled.size + + indirect_view.size + ; + device->CreateBuffer(&bd, nullptr, &generalBuffer); + device->SetName(&generalBuffer, "HairParticleSystem::generalBuffer"); - bd.misc_flags = ResourceMiscFlag::BUFFER_RAW; - bd.stride = sizeof(MeshComponent::Vertex_UVS); - bd.size = bd.stride * 4 * particleCount; - device->CreateBuffer(&bd, nullptr, &vertexBuffer_UVS); - device->SetName(&vertexBuffer_UVS, "HairParticleSystem::vertexBuffer_UVS"); + const uint64_t alignment = device->GetMinOffsetAlignment(&bd); + uint64_t buffer_offset = 0ull; - bd.misc_flags = ResourceMiscFlag::NONE; - bd.bind_flags = BindFlag::INDEX_BUFFER | BindFlag::UNORDERED_ACCESS; - bd.format = ((particleCount * 4) < 65536) ? Format::R16_UINT : Format::R32_UINT; - bd.stride = GetFormatStride(bd.format); - bd.size = bd.stride * 6 * particleCount; - device->CreateBuffer(&bd, nullptr, &culledIndexBuffer); - device->SetName(&culledIndexBuffer, "HairParticleSystem::culledIndexBuffer"); + const uint32_t simulation_stride = sizeof(PatchSimulationData); + simulation_view.offset = buffer_offset; + buffer_offset += AlignTo(simulation_view.size, alignment); + simulation_view.subresource_srv = device->CreateSubresource(&generalBuffer, SubresourceType::SRV, simulation_view.offset, simulation_view.size, nullptr, &simulation_stride); + simulation_view.subresource_uav = device->CreateSubresource(&generalBuffer, SubresourceType::UAV, simulation_view.offset, simulation_view.size, nullptr, &simulation_stride); + simulation_view.descriptor_srv = device->GetDescriptorIndex(&generalBuffer, SubresourceType::SRV, simulation_view.subresource_srv); + simulation_view.descriptor_uav = device->GetDescriptorIndex(&generalBuffer, SubresourceType::UAV, simulation_view.subresource_uav); + + vb_pos[0].offset = buffer_offset; + buffer_offset += AlignTo(vb_pos[0].size, alignment); + vb_pos[0].subresource_srv = device->CreateSubresource(&generalBuffer, SubresourceType::SRV, vb_pos[0].offset, vb_pos[0].size); + vb_pos[0].subresource_uav = device->CreateSubresource(&generalBuffer, SubresourceType::UAV, vb_pos[0].offset, vb_pos[0].size); + vb_pos[0].descriptor_srv = device->GetDescriptorIndex(&generalBuffer, SubresourceType::SRV, vb_pos[0].subresource_srv); + vb_pos[0].descriptor_uav = device->GetDescriptorIndex(&generalBuffer, SubresourceType::UAV, vb_pos[0].subresource_uav); + + vb_pos[1].offset = buffer_offset; + buffer_offset += AlignTo(vb_pos[1].size, alignment); + vb_pos[1].subresource_srv = device->CreateSubresource(&generalBuffer, SubresourceType::SRV, vb_pos[1].offset, vb_pos[1].size); + vb_pos[1].subresource_uav = device->CreateSubresource(&generalBuffer, SubresourceType::UAV, vb_pos[1].offset, vb_pos[1].size); + vb_pos[1].descriptor_srv = device->GetDescriptorIndex(&generalBuffer, SubresourceType::SRV, vb_pos[1].subresource_srv); + vb_pos[1].descriptor_uav = device->GetDescriptorIndex(&generalBuffer, SubresourceType::UAV, vb_pos[1].subresource_uav); + + vb_uvs.offset = buffer_offset; + buffer_offset += AlignTo(vb_uvs.size, alignment); + vb_uvs.subresource_srv = device->CreateSubresource(&generalBuffer, SubresourceType::SRV, vb_uvs.offset, vb_uvs.size); + vb_uvs.subresource_uav = device->CreateSubresource(&generalBuffer, SubresourceType::UAV, vb_uvs.offset, vb_uvs.size); + vb_uvs.descriptor_srv = device->GetDescriptorIndex(&generalBuffer, SubresourceType::SRV, vb_uvs.subresource_srv); + vb_uvs.descriptor_uav = device->GetDescriptorIndex(&generalBuffer, SubresourceType::UAV, vb_uvs.subresource_uav); + + ib_culled.offset = buffer_offset; + buffer_offset += AlignTo(ib_culled.size, alignment); + ib_culled.subresource_srv = device->CreateSubresource(&generalBuffer, SubresourceType::SRV, ib_culled.offset, ib_culled.size, &ib_format); + ib_culled.subresource_uav = device->CreateSubresource(&generalBuffer, SubresourceType::UAV, ib_culled.offset, ib_culled.size, &ib_format); + ib_culled.descriptor_srv = device->GetDescriptorIndex(&generalBuffer, SubresourceType::SRV, ib_culled.subresource_srv); + ib_culled.descriptor_uav = device->GetDescriptorIndex(&generalBuffer, SubresourceType::UAV, ib_culled.subresource_uav); + + const uint32_t indirect_stride = sizeof(IndirectDrawArgsIndexedInstanced); + indirect_view.offset = buffer_offset; + buffer_offset += AlignTo(indirect_view.size, alignment); + indirect_view.subresource_srv = device->CreateSubresource(&generalBuffer, SubresourceType::SRV, indirect_view.offset, indirect_view.size, nullptr, &indirect_stride); + indirect_view.subresource_uav = device->CreateSubresource(&generalBuffer, SubresourceType::UAV, indirect_view.offset, indirect_view.size, nullptr, &indirect_stride); + indirect_view.descriptor_srv = device->GetDescriptorIndex(&generalBuffer, SubresourceType::SRV, indirect_view.subresource_srv); + indirect_view.descriptor_uav = device->GetDescriptorIndex(&generalBuffer, SubresourceType::UAV, indirect_view.subresource_uav); primitiveBuffer = wi::renderer::GetIndexBufferForQuads(particleCount); } @@ -166,16 +203,6 @@ namespace wi device->CreateBuffer(&bd, indices.data(), &indexBuffer); device->SetName(&indexBuffer, "HairParticleSystem::indexBuffer"); } - - if (!indirectBuffer.IsValid()) - { - GPUBufferDesc desc; - desc.stride = sizeof(IndirectDrawArgsIndexedInstanced); - desc.size = desc.stride; - desc.misc_flags = ResourceMiscFlag::BUFFER_STRUCTURED | ResourceMiscFlag::INDIRECT_ARGS; - desc.bind_flags = BindFlag::UNORDERED_ACCESS; - device->CreateBuffer(&desc, nullptr, &indirectBuffer); - } } void HairParticleSystem::CreateRaytracingRenderData() { @@ -191,12 +218,12 @@ namespace wi desc.bottom_level.geometries.emplace_back(); auto& geometry = desc.bottom_level.geometries.back(); geometry.type = RaytracingAccelerationStructureDesc::BottomLevel::Geometry::Type::TRIANGLES; - geometry.triangles.vertex_buffer = vertexBuffer_POS[0]; + geometry.triangles.vertex_buffer = generalBuffer; geometry.triangles.index_buffer = primitiveBuffer; geometry.triangles.index_format = GetIndexBufferFormat(primitiveBuffer.desc.format); geometry.triangles.index_count = GetParticleCount() * 6; geometry.triangles.index_offset = 0; - geometry.triangles.vertex_count = (uint32_t)(vertexBuffer_POS[0].desc.size / vertexBuffer_POS[0].desc.stride); + geometry.triangles.vertex_count = (uint32_t)(vb_pos[0].size / sizeof(MeshComponent::Vertex_POS)); geometry.triangles.vertex_format = Format::R32G32B32_FLOAT; geometry.triangles.vertex_stride = sizeof(MeshComponent::Vertex_POS); @@ -229,16 +256,16 @@ namespace wi CreateFromMesh(mesh); } - if ((_flags & REBUILD_BUFFERS) || !constantBuffer.IsValid() || GetParticleCount() != simulationBuffer.GetDesc().size / sizeof(PatchSimulationData)) + if ((_flags & REBUILD_BUFFERS) || !constantBuffer.IsValid() || GetParticleCount() != simulation_view.size / sizeof(PatchSimulationData)) { CreateRenderData(); } - std::swap(vertexBuffer_POS[0], vertexBuffer_POS[1]); + std::swap(vb_pos[0], vb_pos[1]); if (BLAS.IsValid() && !BLAS.desc.bottom_level.geometries.empty()) { - BLAS.desc.bottom_level.geometries.back().triangles.vertex_buffer = vertexBuffer_POS[0]; + BLAS.desc.bottom_level.geometries.back().triangles.vertex_byte_offset = vb_pos[0].offset; } } void HairParticleSystem::UpdateGPU( @@ -263,7 +290,7 @@ namespace wi { const UpdateGPUItem& item = items[i]; const HairParticleSystem& hair = *item.hair; - if (hair.strandCount == 0 || !hair.simulationBuffer.IsValid()) + if (hair.strandCount == 0 || !hair.generalBuffer.IsValid()) { continue; } @@ -304,25 +331,13 @@ namespace wi args.InstanceCount = 1; args.StartIndexLocation = 0; args.StartInstanceLocation = 0; - device->UpdateBuffer(&hair.indirectBuffer, &args, cmd); - barrier_stack.push_back(GPUBarrier::Buffer(&hair.indirectBuffer, ResourceState::COPY_DST, ResourceState::UNORDERED_ACCESS)); + device->UpdateBuffer(&hair.generalBuffer, &args, cmd, sizeof(args), hair.indirect_view.offset); + barrier_stack.push_back(GPUBarrier::Buffer(&hair.generalBuffer, ResourceState::COPY_DST, ResourceState::UNORDERED_ACCESS)); if (hair.regenerate_frame) { hair.regenerate_frame = false; - device->ClearUAV(&hair.simulationBuffer, 0, cmd); - device->ClearUAV(&hair.vertexBuffer_POS[0], 0, cmd); - device->ClearUAV(&hair.vertexBuffer_POS[1], 0, cmd); - device->ClearUAV(&hair.vertexBuffer_UVS, 0, cmd); - device->ClearUAV(&hair.culledIndexBuffer, 0, cmd); - - barrier_stack.push_back(GPUBarrier::Memory(&hair.simulationBuffer)); - barrier_stack.push_back(GPUBarrier::Memory(&hair.vertexBuffer_POS[0])); - barrier_stack.push_back(GPUBarrier::Memory(&hair.vertexBuffer_POS[1])); - barrier_stack.push_back(GPUBarrier::Memory(&hair.vertexBuffer_UVS)); - barrier_stack.push_back(GPUBarrier::Memory(&hair.culledIndexBuffer)); } - } barrier_stack_flush(); @@ -333,7 +348,7 @@ namespace wi { const UpdateGPUItem& item = items[i]; const HairParticleSystem& hair = *item.hair; - if (hair.strandCount == 0 || !hair.simulationBuffer.IsValid()) + if (hair.strandCount == 0 || !hair.generalBuffer.IsValid()) { continue; } @@ -341,14 +356,11 @@ namespace wi device->BindConstantBuffer(&hair.constantBuffer, CB_GETBINDSLOT(HairParticleCB), cmd); - const GPUResource* uavs[] = { - &hair.simulationBuffer, - &hair.vertexBuffer_POS[0], - &hair.vertexBuffer_UVS, - &hair.culledIndexBuffer, - &hair.indirectBuffer, - }; - device->BindUAVs(uavs, 0, arraysize(uavs), cmd); + device->BindUAV(&hair.generalBuffer, 0, cmd, hair.simulation_view.subresource_uav); + device->BindUAV(&hair.generalBuffer, 1, cmd, hair.vb_pos[0].subresource_uav); + device->BindUAV(&hair.generalBuffer, 2, cmd, hair.vb_uvs.subresource_uav); + device->BindUAV(&hair.generalBuffer, 3, cmd, hair.ib_culled.subresource_uav); + device->BindUAV(&hair.generalBuffer, 4, cmd, hair.indirect_view.subresource_uav); if (hair.indexBuffer.IsValid()) { @@ -370,11 +382,7 @@ namespace wi device->Dispatch((hair.strandCount + THREADCOUNT_SIMULATEHAIR - 1) / THREADCOUNT_SIMULATEHAIR, 1, 1, cmd); - barrier_stack.push_back(GPUBarrier::Memory(&hair.simulationBuffer)); - barrier_stack.push_back(GPUBarrier::Buffer(&hair.indirectBuffer, ResourceState::UNORDERED_ACCESS, ResourceState::INDIRECT_ARGUMENT)); - barrier_stack.push_back(GPUBarrier::Buffer(&hair.vertexBuffer_POS[0], ResourceState::UNORDERED_ACCESS, ResourceState::SHADER_RESOURCE)); - barrier_stack.push_back(GPUBarrier::Buffer(&hair.vertexBuffer_UVS, ResourceState::UNORDERED_ACCESS, ResourceState::SHADER_RESOURCE)); - barrier_stack.push_back(GPUBarrier::Buffer(&hair.culledIndexBuffer, ResourceState::UNORDERED_ACCESS, ResourceState::INDEX_BUFFER)); + barrier_stack.push_back(GPUBarrier::Buffer(&hair.generalBuffer, ResourceState::UNORDERED_ACCESS, ResourceState::INDIRECT_ARGUMENT | ResourceState::INDEX_BUFFER | ResourceState::SHADER_RESOURCE)); } barrier_stack_flush(); @@ -415,9 +423,9 @@ namespace wi device->BindConstantBuffer(&constantBuffer, CB_GETBINDSLOT(HairParticleCB), cmd); device->BindResource(&primitiveBuffer, 0, cmd); - device->BindIndexBuffer(&culledIndexBuffer, GetIndexBufferFormat(culledIndexBuffer.desc.format), 0, cmd); + device->BindIndexBuffer(&generalBuffer, GetIndexBufferFormat(GetParticleCount() * 4), ib_culled.offset, cmd); - device->DrawIndexedInstancedIndirect(&indirectBuffer, 0, cmd); + device->DrawIndexedInstancedIndirect(&generalBuffer, indirect_view.offset, cmd); device->EventEnd(cmd); } diff --git a/WickedEngine/wiHairParticle.h b/WickedEngine/wiHairParticle.h index a80091984..d8343e072 100644 --- a/WickedEngine/wiHairParticle.h +++ b/WickedEngine/wiHairParticle.h @@ -7,6 +7,7 @@ #include "wiPrimitive.h" #include "wiVector.h" #include "wiScene_Decl.h" +#include "wiScene_Components.h" namespace wi { @@ -19,12 +20,13 @@ namespace wi { public: wi::graphics::GPUBuffer constantBuffer; - wi::graphics::GPUBuffer simulationBuffer; - wi::graphics::GPUBuffer vertexBuffer_POS[2]; - wi::graphics::GPUBuffer vertexBuffer_UVS; + wi::graphics::GPUBuffer generalBuffer; + wi::scene::MeshComponent::BufferView simulation_view; + wi::scene::MeshComponent::BufferView vb_pos[2]; + wi::scene::MeshComponent::BufferView vb_uvs; + wi::scene::MeshComponent::BufferView ib_culled; + wi::scene::MeshComponent::BufferView indirect_view; wi::graphics::GPUBuffer primitiveBuffer; - wi::graphics::GPUBuffer culledIndexBuffer; - wi::graphics::GPUBuffer indirectBuffer; wi::graphics::GPUBuffer indexBuffer; wi::graphics::GPUBuffer vertexBuffer_length; diff --git a/WickedEngine/wiScene.cpp b/WickedEngine/wiScene.cpp index b9fc759b2..67363a41b 100644 --- a/WickedEngine/wiScene.cpp +++ b/WickedEngine/wiScene.cpp @@ -661,51 +661,55 @@ namespace wi::scene vxgi.clipmap_to_update = (vxgi.clipmap_to_update + 1) % VXGI_CLIPMAP_COUNT; } - impostor_ib_format = (((objects.GetCount() * 4) < 655536) ? Format::R16_UINT : Format::R32_UINT); - const size_t impostor_index_stride = impostor_ib_format == Format::R16_UINT ? sizeof(uint16_t) : sizeof(uint32_t); - const uint64_t required_impostor_buffer_size = objects.GetCount() * (sizeof(impostor_index_stride) * 6 + sizeof(uint4) * 4 + sizeof(uint2)); - if (impostorBuffer.desc.size < required_impostor_buffer_size) + if (impostors.GetCount() > 0 && objects.GetCount() > 0) { - GPUBufferDesc desc; - desc.usage = Usage::DEFAULT; - desc.size = required_impostor_buffer_size * 2; // *2 to grow fast - desc.bind_flags = BindFlag::INDEX_BUFFER | BindFlag::SHADER_RESOURCE | BindFlag::UNORDERED_ACCESS; - desc.misc_flags = ResourceMiscFlag::BUFFER_RAW | ResourceMiscFlag::INDIRECT_ARGS; - device->CreateBuffer(&desc, nullptr, &impostorBuffer); - device->SetName(&impostorBuffer, "impostorBuffer"); + impostor_ib_format = GetIndexBufferFormatRaw((uint32_t)objects.GetCount() * 4); + const size_t impostor_index_stride = impostor_ib_format == Format::R16_UINT ? sizeof(uint16_t) : sizeof(uint32_t); + const uint64_t required_impostor_buffer_size = objects.GetCount() * (sizeof(impostor_index_stride) * 6 + sizeof(uint4) * 4 + sizeof(uint2)) + sizeof(IndirectDrawArgsIndexedInstanced); + if (impostorBuffer.desc.size < required_impostor_buffer_size) + { + GPUBufferDesc desc; + desc.usage = Usage::DEFAULT; + desc.size = required_impostor_buffer_size * 2; // *2 to grow fast + desc.bind_flags = BindFlag::INDEX_BUFFER | BindFlag::SHADER_RESOURCE | BindFlag::UNORDERED_ACCESS; + desc.misc_flags = ResourceMiscFlag::BUFFER_RAW | ResourceMiscFlag::INDIRECT_ARGS; + device->CreateBuffer(&desc, nullptr, &impostorBuffer); + device->SetName(&impostorBuffer, "impostorBuffer"); - const uint64_t alignment = device->GetMinOffsetAlignment(&desc); - uint64_t buffer_offset = 0ull; + const uint64_t alignment = device->GetMinOffsetAlignment(&desc); + uint64_t buffer_offset = 0ull; - impostor_ib.offset = buffer_offset; - impostor_ib.size = objects.GetCount() * sizeof(impostor_index_stride) * 6; - buffer_offset += AlignTo(impostor_ib.size, alignment); - impostor_ib.subresource_srv = device->CreateSubresource(&impostorBuffer, SubresourceType::SRV, impostor_ib.offset, impostor_ib.size, &impostor_ib_format); - impostor_ib.subresource_uav = device->CreateSubresource(&impostorBuffer, SubresourceType::UAV, impostor_ib.offset, impostor_ib.size, &impostor_ib_format); - impostor_ib.descriptor_srv = device->GetDescriptorIndex(&impostorBuffer, SubresourceType::SRV, impostor_ib.subresource_srv); - impostor_ib.descriptor_uav = device->GetDescriptorIndex(&impostorBuffer, SubresourceType::UAV, impostor_ib.subresource_uav); + impostor_ib.offset = buffer_offset; + impostor_ib.size = objects.GetCount() * sizeof(impostor_index_stride) * 6; + buffer_offset += AlignTo(impostor_ib.size, alignment); + impostor_ib.subresource_srv = device->CreateSubresource(&impostorBuffer, SubresourceType::SRV, impostor_ib.offset, impostor_ib.size, &impostor_ib_format); + impostor_ib.subresource_uav = device->CreateSubresource(&impostorBuffer, SubresourceType::UAV, impostor_ib.offset, impostor_ib.size, &impostor_ib_format); + impostor_ib.descriptor_srv = device->GetDescriptorIndex(&impostorBuffer, SubresourceType::SRV, impostor_ib.subresource_srv); + impostor_ib.descriptor_uav = device->GetDescriptorIndex(&impostorBuffer, SubresourceType::UAV, impostor_ib.subresource_uav); - impostor_vb.offset = buffer_offset; - impostor_vb.size = objects.GetCount() * sizeof(uint4) * 4; - buffer_offset += AlignTo(impostor_vb.size, alignment); - impostor_vb.subresource_srv = device->CreateSubresource(&impostorBuffer, SubresourceType::SRV, impostor_vb.offset, impostor_vb.size); - impostor_vb.subresource_uav = device->CreateSubresource(&impostorBuffer, SubresourceType::UAV, impostor_vb.offset, impostor_vb.size); - impostor_vb.descriptor_srv = device->GetDescriptorIndex(&impostorBuffer, SubresourceType::SRV, impostor_vb.subresource_srv); - impostor_vb.descriptor_uav = device->GetDescriptorIndex(&impostorBuffer, SubresourceType::UAV, impostor_vb.subresource_uav); + impostor_vb.offset = buffer_offset; + impostor_vb.size = objects.GetCount() * sizeof(uint4) * 4; + buffer_offset += AlignTo(impostor_vb.size, alignment); + impostor_vb.subresource_srv = device->CreateSubresource(&impostorBuffer, SubresourceType::SRV, impostor_vb.offset, impostor_vb.size); + impostor_vb.subresource_uav = device->CreateSubresource(&impostorBuffer, SubresourceType::UAV, impostor_vb.offset, impostor_vb.size); + impostor_vb.descriptor_srv = device->GetDescriptorIndex(&impostorBuffer, SubresourceType::SRV, impostor_vb.subresource_srv); + impostor_vb.descriptor_uav = device->GetDescriptorIndex(&impostorBuffer, SubresourceType::UAV, impostor_vb.subresource_uav); - impostor_data.offset = buffer_offset; - impostor_data.size = objects.GetCount() * sizeof(uint2); - buffer_offset += AlignTo(impostor_data.size, alignment); - impostor_data.subresource_srv = device->CreateSubresource(&impostorBuffer, SubresourceType::SRV, impostor_data.offset, impostor_data.size); - impostor_data.subresource_uav = device->CreateSubresource(&impostorBuffer, SubresourceType::UAV, impostor_data.offset, impostor_data.size); - impostor_data.descriptor_srv = device->GetDescriptorIndex(&impostorBuffer, SubresourceType::SRV, impostor_data.subresource_srv); - impostor_data.descriptor_uav = device->GetDescriptorIndex(&impostorBuffer, SubresourceType::UAV, impostor_data.subresource_uav); + impostor_data.offset = buffer_offset; + impostor_data.size = objects.GetCount() * sizeof(uint2); + buffer_offset += AlignTo(impostor_data.size, alignment); + impostor_data.subresource_srv = device->CreateSubresource(&impostorBuffer, SubresourceType::SRV, impostor_data.offset, impostor_data.size); + impostor_data.subresource_uav = device->CreateSubresource(&impostorBuffer, SubresourceType::UAV, impostor_data.offset, impostor_data.size); + impostor_data.descriptor_srv = device->GetDescriptorIndex(&impostorBuffer, SubresourceType::SRV, impostor_data.subresource_srv); + impostor_data.descriptor_uav = device->GetDescriptorIndex(&impostorBuffer, SubresourceType::UAV, impostor_data.subresource_uav); - impostor_indirect.offset = buffer_offset; - impostor_indirect.size = sizeof(IndirectDrawArgsIndexedInstanced); - buffer_offset += AlignTo(impostor_data.size, alignment); - impostor_indirect.subresource_uav = device->CreateSubresource(&impostorBuffer, SubresourceType::UAV, impostor_indirect.offset, impostor_indirect.size); + const uint32_t indirect_stride = sizeof(IndirectDrawArgsIndexedInstanced); + impostor_indirect.offset = buffer_offset; + impostor_indirect.size = sizeof(IndirectDrawArgsIndexedInstanced); + buffer_offset += AlignTo(impostor_data.size, alignment); + impostor_indirect.subresource_uav = device->CreateSubresource(&impostorBuffer, SubresourceType::UAV, impostor_indirect.offset, impostor_indirect.size, nullptr, &indirect_stride); + } } // Shader scene resources: @@ -4241,9 +4245,9 @@ namespace wi::scene geometry.indexOffset = 0; geometry.materialIndex = (uint)materials.GetIndex(entity); geometry.ib = device->GetDescriptorIndex(&hair.primitiveBuffer, SubresourceType::SRV); - geometry.vb_pos_nor_wind = device->GetDescriptorIndex(&hair.vertexBuffer_POS[0], SubresourceType::SRV); - geometry.vb_pre = device->GetDescriptorIndex(&hair.vertexBuffer_POS[1], SubresourceType::SRV); - geometry.vb_uvs = device->GetDescriptorIndex(&hair.vertexBuffer_UVS, SubresourceType::SRV); + geometry.vb_pos_nor_wind = hair.vb_pos[0].descriptor_srv; + geometry.vb_pre = hair.vb_pos[1].descriptor_srv; + geometry.vb_uvs = hair.vb_uvs.descriptor_srv; geometry.flags = SHADERMESH_FLAG_DOUBLE_SIDED | SHADERMESH_FLAG_HAIRPARTICLE; geometry.meshletOffset = 0; geometry.meshletCount = meshletCount; diff --git a/WickedEngine/wiScene_Components.h b/WickedEngine/wiScene_Components.h index 596c88b12..9e329bb0e 100644 --- a/WickedEngine/wiScene_Components.h +++ b/WickedEngine/wiScene_Components.h @@ -435,7 +435,7 @@ namespace wi::scene inline bool IsDynamic() const { return _flags & DYNAMIC; } inline float GetTessellationFactor() const { return tessellationFactor; } - inline wi::graphics::IndexBufferFormat GetIndexFormat() const { return vertex_positions.size() > 65536 ? wi::graphics::IndexBufferFormat::UINT32 : wi::graphics::IndexBufferFormat::UINT16; } + inline wi::graphics::IndexBufferFormat GetIndexFormat() const { return wi::graphics::GetIndexBufferFormat((uint32_t)vertex_positions.size()); } inline size_t GetIndexStride() const { return GetIndexFormat() == wi::graphics::IndexBufferFormat::UINT32 ? sizeof(uint32_t) : sizeof(uint16_t); } inline bool IsSkinned() const { return armatureID != wi::ecs::INVALID_ENTITY; } inline uint32_t GetLODCount() const { return subsets_per_lod == 0 ? 1 : ((uint32_t)subsets.size() / subsets_per_lod); } diff --git a/WickedEngine/wiVersion.cpp b/WickedEngine/wiVersion.cpp index 656f36bd2..3184aa7be 100644 --- a/WickedEngine/wiVersion.cpp +++ b/WickedEngine/wiVersion.cpp @@ -9,7 +9,7 @@ namespace wi::version // minor features, major updates, breaking compatibility changes const int minor = 71; // minor bug fixes, alterations, refactors, updates - const int revision = 225; + const int revision = 226; const std::string version_string = std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(revision);